Compare commits

..

238 Commits

Author SHA1 Message Date
Ben Alpert
56517a5423 Blog post for 0.9 release candidate 2014-02-16 19:37:24 -08:00
Ben Alpert
ec58683389 Fix typo in latest round-up 2014-02-15 22:54:32 -08:00
Jonas Gebhardt
be569b1ee1 Add community round-up #16 2014-02-15 15:54:40 -08:00
Paul O’Shannessy
407589bd96 Center twitter embeds differently. again.
This time, just target the iframe. display: table was weird in webkit.
2014-02-05 16:23:43 -08:00
Paul O’Shannessy
084f24e3e7 Don't use <center> for twitter embeds 2014-02-05 15:52:59 -08:00
Jonas Gebhardt
acf97b26ca Community Round-Up #15; center embedded tweets 2014-02-05 15:52:59 -08:00
Paul O’Shannessy
ccf00ccf08 Revert "Update propTypes documentation."
This reverts commit b66fbde0a9.
2014-02-05 15:05:41 -08:00
Pete Hunt
7f22f43fb1 Update example-apps.md 2014-02-02 04:02:17 +01:00
petehunt
92092073ca add example apps page 2014-02-02 04:02:10 +01:00
petehunt
3c19f6253b Add a complementary tools page 2014-02-02 04:01:56 +01:00
Pete Hunt
7467b1fb39 Update videos.md 2014-02-02 04:01:48 +01:00
petehunt
c06ca2305f Add link to meteor talk 2014-02-02 04:01:37 +01:00
Ben Alpert
3810c839a7 [docs] Fix comma splice 2014-02-02 03:51:23 +01:00
Ben Alpert
571d173182 Disable CodeMirror smart indentation
Fixes #966.
2014-02-02 03:51:16 +01:00
Christopher Chedeau
22772c9862 s/Mock DOM/Virtual DOM/
Let's be consistent with the naming
2014-02-02 03:51:07 +01:00
Kunal Mehta
f9704536d1 Add documentation about React.renderComponent
Recently learned that components passed into `React.renderComponent` may not be the ones actually mounted. Also learned that it returns the mounted component. Added some documentation describing this.
2014-02-02 03:50:58 +01:00
Eric Schoffstall
64ac427395 fix grammar mistake 2014-02-02 03:50:26 +01:00
Paul O’Shannessy
dd66223d67 Fix animation example code
key should never be index into an array or there are bugs. Especially in
transitions.

Fixes #853
2014-02-02 03:49:58 +01:00
Ben Alpert
6e4ddfd239 Fix docs typo 2014-02-02 03:49:48 +01:00
petehunt
3120192172 remove references to react-page 2014-02-02 03:49:41 +01:00
Bob Eagan
3db3460868 add hash link for lifecycle section of working with the browser page 2014-02-02 03:49:14 +01:00
Bob Eagan
2edb76f558 fix incorrect link 2014-02-02 03:48:41 +01:00
Ayman Osman
09650e1dc3 Fix typo 2014-02-02 03:47:54 +01:00
Jean Lauliac
0681d1386b Normalize internal links in 'why react' article 2014-02-02 03:47:16 +01:00
Jean Lauliac
341d292665 Update broken link in 'why react' article 2014-02-02 03:47:01 +01:00
cpojer
b66fbde0a9 Update propTypes documentation. 2014-02-02 03:46:42 +01:00
Cheng Lou
8c8841c83a [docs] Tweak frontpage first example and jsx-compiler example 2014-02-02 03:45:31 +01:00
Ben Alpert
c7f0663176 Simplify live editor execution logic 2014-02-02 03:45:21 +01:00
Ben Alpert
d3fc5adf39 Properly clear live editor on JSX compile failure 2014-02-02 03:45:15 +01:00
Ben Alpert
761e1c8080 Update homepage for new JSX/JS editor 2014-02-02 03:44:58 +01:00
Paul O’Shannessy
6b1c6be974 Normalize line endings 2014-02-02 03:44:44 +01:00
Cheng Lou
7ac5f3c7cf docs add jsx->js tab to live editors 2014-02-02 03:43:43 +01:00
Cheng Lou
6b15ad5f6d docs fix back link in Examples 2014-02-02 03:43:26 +01:00
Nick Thompson
542f20b822 Clarify componentWillMount behavior 2014-02-02 03:42:40 +01:00
Christopher Chedeau
30e16e4e63 Document isMounted
Text from @petehunt
2014-02-02 03:42:15 +01:00
Paul O’Shannessy
7c4c0cdd01 [docs] Remove commented out ghbtns 2014-01-15 11:39:52 -08:00
Ben Alpert
92102ac31d Add info about dev vs. prod builds
Also moved the dev builds first because that's what most people will want.
2014-01-15 11:35:51 -08:00
Paul O’Shannessy
277cbf06e4 [docs] Add timezone to _config
This way we hopefully won't churn the feed when genereated in
a different time zone (eg France).
2014-01-15 11:12:02 -08:00
Paul O’Shannessy
b0b771763b Remove stray "117", combine lines in polyfill docs 2014-01-15 11:09:24 -08:00
Richard Feldman
8d63dad433 Rewrite Older Browsers polyfill section for clarity. 2014-01-15 10:52:39 -08:00
Timothy Yung
edd61edfb1 Fix "Uncontrolled Components" documentation 2014-01-15 10:52:38 -08:00
Richard Feldman
d99cafaf9a Fix typo in docs. 2014-01-15 10:52:38 -08:00
Richard Feldman
190f373ce3 Update docs to mention that you need both es5-shim.js and es5-sham.js to use React with IE8. 2014-01-15 10:52:38 -08:00
Ben Alpert
1873e1d0a9 Add dataType to all $.ajax calls for consistency
Fixes https://groups.google.com/forum/#!topic/reactjs/WWA3ZqU6y4w.
2014-01-15 10:52:38 -08:00
Christoph Pojer
27ac8a3224 Fix #845, Trivial year change
This was accidentally pulled into gh-pages.
2014-01-15 10:52:38 -08:00
Christoph Pojer
97f2441b7e Fix #874: Edit thinking-in-react
Accidentally pulled #874 into gh-pages.
2014-01-15 10:52:38 -08:00
Ben Alpert
ce72e84234 Document return value of unmountComponentAtNode 2014-01-15 10:52:38 -08:00
Ben Alpert
52ad24f788 Remove two more react.min.js references 2014-01-15 10:52:38 -08:00
Paul O’Shannessy
7efdb43742 Don't use the min build in getting started guide 2014-01-15 10:52:38 -08:00
Michal Srb
51e7a6bae1 Fix URL in displayName description 2014-01-15 10:52:38 -08:00
Ben Alpert
f44e8ccd40 Add charCode/keyCode/which to key event docs 2014-01-15 10:52:38 -08:00
Vjeux
60b5520fee Revert "adding warning about the lack of support for onScroll on IE8"
This reverts commit 8615ade2b6.
2014-01-06 18:35:50 +01:00
Vjeux
658aa45483 Community Round-up #14 2014-01-06 18:15:56 +01:00
Daniel Lo Nigro
ea41991825 Change “not allowed” back to “discouraged” since you technically *can* use props called class or for 2014-01-06 18:15:24 +01:00
Daniel Lo Nigro
5cbc727f68 Add link to HTML to JSX converter to “JSX In Depth” page 2014-01-06 18:15:19 +01:00
xixixao
ee90857dfb Document displayName 2014-01-06 18:15:13 +01:00
Pascal Hartig
8ef2cec2c4 Add gulp-react to Helpful OSS Projects
Add @sindresorhus' JSX task for Gulp to the "Helpful Open-Source Projects" section of the tooling integration docs.
2014-01-06 18:15:07 +01:00
Ben Alpert
3afe6dee51 Fix typo 2014-01-06 18:14:59 +01:00
Ben Alpert
13c211a6a6 Mention react-art where we talk about SVG 2014-01-06 18:14:50 +01:00
Felipe Oliveira Carvalho
e23e627091 Remove the require-jsx plugin from the tooling-integration page
In favor of the r.js friendly jsx-requirejs-plugin
2014-01-06 18:14:40 +01:00
Felipe Oliveira Carvalho
978a8f5807 Add jsx-requirejs-plugin to the tooling-integration page 2014-01-06 18:14:31 +01:00
Fabio Costa
8615ade2b6 adding warning about the lack of support for onScroll on IE8
Adding `console.warn` about the lack of support for `onScroll` event on IE8
Related to this issue on github https://github.com/facebook/react/issues/631
2014-01-06 18:14:02 +01:00
Vjeux
dbae31d36f React Chrome Developer Tools 2014-01-02 21:05:37 +01:00
Cheng Lou
8d37f7d373 docs better error display for live editor and JSX compiler 2014-01-02 21:05:27 +01:00
Cheng Lou
8dc36e396b docs tips fix small typo and code 2014-01-02 21:05:20 +01:00
Cheng Lou
c5a2ca997c docs remove link to wiki page
Also some minor writing changes.
2013-12-31 05:59:08 +01:00
Ben Alpert
32753c59d4 Upgrade codemirror and enable line wrapping
Fixes #678.
2013-12-31 05:58:46 +01:00
Vjeux
16072437c3 Making 'native DOM' nodes more explicit in documentation 2013-12-31 01:38:22 +01:00
Ben Alpert
5e441d656f IE8 style fixes
- Add html5shiv so that HTML5 elements like header, footer, etc can be styled
- Remove a couple uses of :first-child/:last-child which IE8 doesn't support
2013-12-31 01:25:10 +01:00
Cheng Lou
0b63c665eb docs tips small refactorings 2013-12-31 00:13:10 +01:00
Ben Alpert
30178d4baf Make React website work in IE8
Fixes #406.

Empty conditional comment is for http://www.phpied.com/conditional-comments-block-downloads/.
2013-12-30 23:46:55 +01:00
Wincent Colaiuta
0e95e8e76d Fix a typo in the working-with-the-browser docs 2013-12-30 23:44:07 +01:00
Cheng Lou
cdb328be92 docs tips expose component function 2013-12-30 23:43:30 +01:00
jhiswin
4b7eb66b31 live_editor.js using deprecated function
unmountAndReleaseReactRootNode -> unmountComponentAtNode
breaks html-jsx.html
2013-12-30 19:57:41 +01:00
petehunt
b55ebc0a95 Update parent/child communication tip 2013-12-30 19:45:40 +01:00
Vjeux
3a370b8db5 Community Round-up #13 2013-12-30 18:30:56 +01:00
Ben Alpert
12b94b0a8c Move initial $.ajax out of getInitialState
We want to encourage people to make pure getInitialState functions.
2013-12-30 18:30:48 +01:00
Ivan Kozik
880951f08c console.log -> console.error 2013-12-30 18:30:12 +01:00
Ivan Kozik
838589c37a Add a warning about the @jsx declaration 2013-12-30 18:30:07 +01:00
Ivan Kozik
0ae26fed60 Use explicit $.ajax dataType and add error callback 2013-12-30 18:30:00 +01:00
Cheng Lou
c68b972618 docs add warning to add jsx pragma 2013-12-30 18:29:53 +01:00
Cheng Lou
a35671a6ec docs remove video at the bottom 2013-12-24 07:45:37 +01:00
Vjeux
5a571e0777 Add a talks section to the docs 2013-12-24 01:31:56 -05:00
Fabio M. Costa
645e25d7a8 language update as suggested by @petehunt 2013-12-24 00:49:19 -05:00
Fabio M. Costa
fa42d0cc6d updating text as suggested by @petehunt 2013-12-24 00:49:11 -05:00
Fabio M. Costa
0a8c2bb272 Adding note about onScroll on IE8 2013-12-24 00:49:06 -05:00
Fabio M. Costa
8de5a925fa Note about react's version on the talk, since somethings have already changed since then 2013-12-24 00:48:57 -05:00
Vjeux
14e05c9dbb typo 2013-12-23 18:54:16 +01:00
Vjeux
219f25c812 Fix html-jsx compiler
It changed React Playground to add a required props but unfortunately didn't update the call sites of the front-page. I don't think it should be required so I'm just making it optional and providing the correct default value.

Test Plan:
 - Open the front page and make sure examples are working
 - Open /react/jsx-compiler.html and make sure it is working
 - Open /react/html-jsx.html and make sure it is working
2013-12-23 18:32:13 +01:00
Daniel Lo Nigro
c7a915993e Simple HTML to JSX converter, built during Hackathon 40 at Facebook.
See /react/html-jsx.html. Not directly linked from the site yet as there may still be some minor issues with it.
2013-12-23 18:32:04 +01:00
Vjeux
6d822d4149 Community Round-up #12 2013-12-23 18:04:55 +01:00
Vjeux
b95fee3c0b Revert "Simple HTML to JSX converter, built during Hackathon 40 at Facebook."
This reverts commit 2308f95316.
2013-12-23 07:01:12 +01:00
Daniel Lo Nigro
2308f95316 Simple HTML to JSX converter, built during Hackathon 40 at Facebook.
See /react/html-jsx.html. Not directly linked from the site yet as there may still be some minor issues with it.
2013-12-23 06:14:39 +01:00
Cheng Lou
dbc8563dfb docs make all link start with /react/docs 2013-12-23 06:14:32 +01:00
Cheng Lou
7eae8d3c4a docs add input attrs for Dom Differences 2013-12-23 06:14:00 +01:00
Kit Randel
37e544d817 Tutorial template markup needs a reference to jquery for the ajax calls
from step 13 onwards.
2013-12-23 06:12:45 +01:00
Jared Forsyth
cd2fd806dc one liner 2013-12-23 06:12:38 +01:00
Jared Forsyth
cb0cbcc305 changes as requested 2013-12-23 06:12:33 +01:00
Jared Forsyth
4f71ddfe5f adding note about initializing state w/ props 2013-12-23 06:12:27 +01:00
Nicholas Bergson-Shilcock
18410bf130 Fix typo (ot -> to) 2013-12-23 06:11:21 +01:00
Jared Forsyth
1a9b21313e fixing capitalization 2013-12-23 06:11:10 +01:00
Jared Forsyth
9686487e3a rename this tip to be less confusing
Using props to initialize state is completely fine; the issue is using state as a "cache" for values calculated based off of props. This title makes it more clear.
2013-12-23 06:11:03 +01:00
Brian Cooke
38d68fd1c5 Update highlighted lines in tutorial
Minor issue, but I found it distracting that the highlighted lines were not accurate. I *believe* this fixes them up.
2013-12-23 06:10:40 +01:00
Vjeux
0993b61fe8 Add video at the bottom of the front page 2013-12-23 06:10:23 +01:00
Vjeux
8f24fcae05 Document the Diff algorithm
We often refer to it but never did actually explain it.
2013-12-23 06:04:47 +01:00
Cheng Lou
94c100cc7a docs section for non-dom attributes
Also added documentation for `dangerouslySetInnerHTML`.
2013-12-23 06:04:42 +01:00
Paul O’Shannessy
b9579e444b 0.8 starter kit 2013-12-19 13:16:07 -08:00
Paul O’Shannessy
4630540f87 v0.8 blog post 2013-12-19 10:42:22 -08:00
Paul O’Shannessy
ece573e7fe Update materials for 0.8.0 2013-12-19 10:41:49 -08:00
Paul O’Shannessy
2e1e868080 v0.8.0 2013-12-19 10:41:03 -08:00
Paul O’Shannessy
e78b01f090 Fix npm-react build task, add to release 2013-12-19 10:31:43 -08:00
Paul O’Shannessy
c7562cf924 Update AUTHORS for 0.8 2013-12-19 09:35:17 -08:00
Paul O’Shannessy
b90ec8a8ec Add newest starter-kit downloads to docs 2013-12-18 17:01:30 -08:00
Paul O’Shannessy
b4cc540a7b Add starter-kit zip files to repo
These should be included so that anybody can build and update the docs
with as little confusion as possible.

I've left the directory in .gitignore so additions need to be
intentional as part of a release.
2013-12-18 17:01:30 -08:00
Paul O’Shannessy
76dc1f7661 Changelog, blog post for 0.5.2, 0.4.2 2013-12-18 16:46:31 -08:00
Paul O’Shannessy
e9b8edd4ba Update readme for 0.5.2 2013-12-18 16:46:31 -08:00
Paul O’Shannessy
0c05167b33 Update npm-react error to point to autoflow 2013-12-17 11:22:07 -08:00
Paul O’Shannessy
77bd2cc1f3 Update npm-react readme to point to autoflow 2013-12-17 11:22:07 -08:00
Paul O’Shannessy
102e1d1fb3 Don't call utils.traverse in transform
Accidental change we missed in review of #495.
2013-12-17 11:10:23 -08:00
Andreas Svensson
50979ffa9e utils.* is now used everywhere 2013-12-17 11:10:23 -08:00
Andreas Svensson
65818f9716 JSXTransformer now supports IE8
Conflicts:
	package.json
2013-12-17 11:10:20 -08:00
Thomas Aylott
65026b1008 fixes ReactTextComponent rootID unescapedness 2013-12-17 10:45:01 -08:00
Thomas Aylott
c24efdba9c test case for ReactTextComponent rootID escaping 2013-12-17 10:45:01 -08:00
Fabio M. Costa
dba52065c9 URL -> url 2013-12-17 10:45:01 -08:00
Josh Duck
7f156bebbf Fix SelectEventPlugin
mouseup was not fired when context menu showed, so select events stopped being fired.
2013-12-17 10:45:01 -08:00
Ben Alpert
8048f96b42 Add loop property 2013-12-17 10:45:01 -08:00
Fabio M. Costa
17b456cfee match -> test
Using RegExp method `test` because this is what is wanted
2013-12-17 10:45:01 -08:00
Fabio M. Costa
432109783a Improving never seen error message
Removing repeating "support it" and fixing camelCase method name
2013-12-17 10:45:01 -08:00
Paul O’Shannessy
93fc40c680 Clean trailing space and lint 2013-12-17 10:45:01 -08:00
Andreas Svensson
fb656ad9ab corrections 2013-12-17 10:45:01 -08:00
Andreas Svensson
36cf618ee7 Fix ReactDOMTextarea missing "rows" and "cols" attribute, incorrect "size" property 2013-12-17 10:45:01 -08:00
Andreas Svensson
68edaa3cfd Add HAS_POSITIVE_NUMERIC_VALUE to DOMProperty and normalize behavior of null values
Uniformly remove null values, rather than sometimes set/remove, could potentially assign 'null' or 'undefined'
2013-12-17 10:45:01 -08:00
Paul O’Shannessy
6235c6b346 Update shrinkwrap 2013-12-13 15:17:26 -08:00
Thomas Aylott
1bf4de4110 fixes browserify task transforms support 2013-12-13 15:08:38 -08:00
Paul O’Shannessy
57b34a120e Move npm-react-core to npm-react, fix tasks accordingly 2013-12-13 14:24:14 -08:00
Paul O’Shannessy
d0be71c8f3 Update react package readme 2013-12-13 14:24:14 -08:00
petehunt
c278a788ac Version bump, make tests work
Conflicts:
	grunt/tasks/populist.js
	package.json
	src/core/React.js
2013-12-13 14:24:11 -08:00
petehunt
1dd0ae5eb7 update README 2013-12-13 14:15:57 -08:00
petehunt
207f2ddb00 version bump to 0.8 to get on top of react.js
Conflicts:
	package.json
2013-12-13 14:15:54 -08:00
petehunt
1188ba5047 rename to with associated warnings 2013-12-13 14:14:42 -08:00
petehunt
caebca54b8 rename to with associated warnings 2013-12-13 14:14:42 -08:00
petehunt
39b7ba2842 revert muffinize :( 2013-12-13 14:14:42 -08:00
petehunt
280243f28b response to code review 2013-12-13 14:14:42 -08:00
petehunt
5361a2bc92 update npm-react-core package.json 2013-12-13 14:14:42 -08:00
Paul O’Shannessy
4262a4089e react-core npm module 2013-12-13 14:14:42 -08:00
petehunt
66b7a5ba0c muffinification 2013-12-13 14:14:42 -08:00
petehunt
0d69d37d06 first work: __DEV__
fix invariant

Get browserify working

remove dead code elimination step since it is not needed due to minifier

use industry standard NODE_ENV

Conflicts:
	grunt/config/browserify.js
	package.json
2013-12-13 14:14:40 -08:00
Ben Newman
92fd516ab8 Explicitly require the assert module in vendor/constants.js. 2013-12-13 14:12:45 -08:00
Ben Newman
0b584b9f8e Better comments for vendor/constants.js. 2013-12-13 14:12:45 -08:00
Ben Newman
1d9a0ce7ff Rewrite vendor/constants.js to use require("ast-types").traverse.
Most notably, this new style of transformation gives us access to
this.parent.node, which allows us to avoid replacing identifiers that are
not actually free variables, such as member expression properties.

Closes #496.

Conflicts:
	package.json
2013-12-13 14:11:22 -08:00
Paul O’Shannessy
a426f1f216 Update depedencies 2013-12-13 13:46:48 -08:00
Paul O’Shannessy
107fbfa809 Disable AnalyticsEventPlugin-test
It gets stuck in web worker issues for some reason. I don't particularly
care and I don't think any of the changes we merged in should be
actually breaking it.
2013-12-13 13:44:35 -08:00
Thomas Aylott
c93db82538 skip Worker test unless the browser supports them 2013-12-12 16:38:05 -08:00
Sean Kinsey
f1a4b84e4c [ReactTransitionGroup] Add onTransitionEnter and onTransitionLeave
It is valuable to know when the number of children in a TransitionGroup is going
to increase or decrease, since we might want to apply extra animations.
For instance, when used with overflow:auto, we might want to apply different css
based on it overflowing or not - to do this we need to calculate this after new
nodes has entered and after nodes has been removed.
2013-12-12 16:01:50 -08:00
John Watson
6438a87264 Separate replaceState invariant violations
It'd be nice if we knew which error we were hitting when this invariant hit.
2013-12-12 16:01:50 -08:00
Ben Alpert
8cb528f0d3 Remove unused updatePropertiesByID 2013-12-12 16:01:50 -08:00
Pete Hunt
656e1bd1b1 Fix lint warnings 2013-12-12 16:01:50 -08:00
Ben Alpert
b0a8103668 Add missing license header 2013-12-12 16:01:49 -08:00
Ben Alpert
7c702fd312 Remove unused event plugin registrationNamesKeys 2013-12-12 16:01:49 -08:00
Ben Alpert
52c7c95be6 ReactErrorUtils: In prod, just return the original
This will save a stack frame (nice when in a debugger) and presumably be a bit faster.
2013-12-12 16:01:49 -08:00
Ben Alpert
b6c7300d48 Don't use .returnValue if .defaultPrevented exists
`.defaultPrevented` exists in IE9+. I checked in IE9, Chrome, and Firefox that it does default to `false`.

Fixes #527.
2013-12-12 16:01:49 -08:00
Christoph Pojer
bc219a2d6e Ensure ReactPerf always uses a string as a URL 2013-12-12 16:01:49 -08:00
Paul O'Shannessy
ad693d9541 order object properties consistently 2013-12-12 16:01:49 -08:00
Pete Hunt
2d5142bc35 Better error message for renderComponentToString()
Reported on Twitter by AirBnb (who are integrating React into their open-source JS framework). They made a mistake and passed a string in as the
component. We should have a better error message for that.
2013-12-12 16:01:49 -08:00
Marshall Roch
6f9f371d2b Rename receiveProps to receiveComponent
This renames receiveProps and changes it to take the next component to copy props from instead of just the props. That is,

  component.receiveComponent(nextComponent, transaction)

instead of

  component.receiveProps(nextComponent.props, transaction)

This is a precursor to adding contexts, which will also need to get propagated just like props. This change allows ReactCompositeComponent to override `receiveProps` and do something like

  this._pendingContext = nextComponent.context;

Conflicts:
	src/core/ReactCompositeComponent.js
2013-12-12 16:01:43 -08:00
Simon Højberg
9e9b3f7348 Transitions: Handle undefined input to mergeKeySet
Gracefully handle undefined input to mergeKeySet.
2013-12-12 15:58:54 -08:00
Simon Højberg
012ac24728 ReactTransitions: Don't animate undefined children 2013-12-12 15:58:54 -08:00
Brian Kim
4915a63973 Fix failing tests
Two of your tests were failing because of commit
1e71df5399
I fixed them by:
1) Using jasmine's spyOn in ReactCompositeComponentError-test.js
2) Inverting the function wrapping in the above commit.
Godspeed.
2013-12-12 15:58:54 -08:00
Tim Yung
55c5178a55 Rename nodeContains to containsNode
Conflicts:
	src/core/ReactMount.js
2013-12-12 15:58:51 -08:00
Mouad Debbar
f142b9b99b Add support for oncontextmenu in React. 2013-12-12 15:57:00 -08:00
Felix Kling
4eb9487c97 Improve error logging for event handlers of React components.
This guards every auto-bound method and uses the name of the component and method as guard name.
2013-12-12 15:57:00 -08:00
Andreas Svensson
3f31ee8d3c Fix wheelDelta misspelled 2013-12-12 15:57:00 -08:00
Ben Alpert
89480e9f38 Make submit button default value appear correctly
Fixes #473.
2013-12-12 15:57:00 -08:00
SanderSpies
4361fb36f9 Removing 'isEventSupported' 2013-12-12 15:57:00 -08:00
SanderSpies
e1fce03d64 Removing unused useSelect variable. 2013-12-12 15:57:00 -08:00
Laurence Rowe
0b4f89cecb Script async and defer properties 2013-12-12 15:57:00 -08:00
Paul O’Shannessy
c09bc39a34 Oxford comma 2013-12-12 15:57:00 -08:00
Josh Duck
996cda82e1 Fix ReactDOMSelection for IE 11
IE 11 no longer supports the legacy document.selection API.
Their implementation of window.getSelection() doesn't support
the extend() method, which we were relying on.

If the selection is RTL and selection extend is missing, then just
flip the selection.
2013-12-12 15:57:00 -08:00
Matti Nelimarkka
efa3618955 Clear error message when rendering a nonvalid component 2013-12-12 15:57:00 -08:00
Tim Yung
c6d2f06697 Better getUnboundedScrollPosition for windows
Instead of using browser sniffing, `getUnboundedScrollPosition` can do
better and not have to depend on the `getDocumentScrollElement` module.
2013-12-12 15:56:59 -08:00
Paul O'Shannessy
06edb20cdf Reorder DefaultDOMPropertyConfig
`autoCorrect` belongs with the non-standard properties list.
2013-12-12 15:56:59 -08:00
Mark Richardson
f4da9418f2 Add autoCorrect to list of supported DOM properties 2013-12-12 15:56:59 -08:00
Tim Yung
7ecd72e724 Forward Compatibility w/ WebKit & Blink
Newer versions of WebKit and Blink will support both `document.body.scrollTop` and `document.documentElement.scrollTop`. Therefore, implementing cross-browser compatibility by summing the two will no longer work.

This changes React to use `getUnboundedScrollPosition` so we get the fix and consistency in one change!

See: https://rniwa.com/2013-10-29/web-compatibility-story-of-scrolltop-and-scrollleft/
2013-12-12 15:56:59 -08:00
Cheng Lou
48af9c7bda docs tips parent-child communication 2013-12-02 15:49:27 -08:00
Paul O’Shannessy
1da10d718d Fix blog pagination
I missed this in the Jekyll upgrade.
2013-12-02 15:47:21 -08:00
Paul O’Shannessy
ef8bd04b04 [docs] Fix download links to addons builds 2013-12-02 15:14:52 -08:00
Pete Hunt
030835b914 Merge pull request #440 from petehunt/new-taglines
New marketing copy
2013-12-02 15:10:24 -08:00
Ben Alpert
abf199d5ff Tweaks to README
Most significant change is updating the leading copy to match #440.
2013-12-02 15:10:12 -08:00
petehunt
1053a1453a Fix frontpage example to retain selection 2013-12-02 15:10:12 -08:00
Cheng Lou
b8194d92f6 docs add download links for react-with-addons 2013-12-02 15:10:12 -08:00
Cheng Lou
18a6b0b94b make docs jsx compiler highlight transpiled js code 2013-12-02 15:10:12 -08:00
Sundeep Malladi
0b31175238 Minor spelling correction in docs 2013-12-02 15:10:12 -08:00
Cheng Lou
6a0bb61b16 docs select value to control chosen option 2013-12-02 15:10:12 -08:00
Ben Alpert
c065b03b8a autoBind -> Autobinding
We don't use the term autoBind anywhere any more.
2013-12-02 15:10:12 -08:00
Levi McCallum
c32c788e5a Add explination of autoBind to DOM Event Listener tip 2013-12-02 15:10:12 -08:00
Paul O’Shannessy
4a0a14d319 Put nav data in "_data"
New in Jekyll 1.3 - http://jekyllrb.com/docs/datafiles/
2013-11-20 23:34:10 -08:00
Paul O’Shannessy
a55d44efaf Fix pagination 2013-11-20 23:34:10 -08:00
Paul O’Shannessy
08fcec503c Update jekyll to 1.3 2013-11-20 23:34:10 -08:00
Cheng Lou
cd6d43e4c0 docs highlight className and htmlFor transforms 2013-11-19 23:28:27 +01:00
Cheng Lou
c329eb6335 docs classSet semicolons missing 2013-11-19 23:28:27 +01:00
Paul O’Shannessy
215988f879 Merge branch 'chenglou-classSet'
closes #463
2013-11-19 23:27:40 +01:00
Ben Alpert
fb7e157cba Make doc headers clickable again
...without preventing clicks on other things.

Just use an `<a name="...">` tag that doesn't take up any space to make sure that we're not covering up something else.

For whatever reason, doing `position: relative; top: -$navHeight;` doesn't work and causes the anchor target not to be moved up. This solution works in both Chrome and Firefox.
2013-11-19 23:24:49 +01:00
Vjeux
8ead6dce76 Community round-up #11 2013-11-19 22:57:46 +01:00
Paul O’Shannessy
79b09d9597 Merge pull request #362 from mcsheffrey/feat-documentation-cookbook
React Tips documentation
2013-11-14 15:06:05 -08:00
Cheng Lou
fb1a072739 fix doc & example transition opacity from .99 to 1
The initial thought was that an opacity animation from 0.01 to 1 causes trouble on some browser. But after testing on opera 12.15, ff 23, ie 10, chrome 30, desktop/mobile safari 7 and chrome android I confirm this works.
2013-11-13 17:55:03 -08:00
Pieter Vanderwerff
c1c7a601dd Added clearfix to blog content holder 2013-11-13 17:54:31 -08:00
Fabio M. Costa
adad0d72be Fixes the name of the component on documentation
AvatarImage -> Avatar
2013-11-13 17:54:02 -08:00
Guido Bouman
e7f48a6c00 Prevents header anchors from interfering with clickable content. 2013-11-13 17:54:02 -08:00
petehunt
d3cee1ee2e Make state immutable in tutorial (eek) 2013-11-08 13:31:45 -08:00
Cheng Lou
d47d509637 move docs tooling from JSX in Depth
Also removes the code wrap around the syntax highlighting link.
2013-11-08 13:31:34 -08:00
Vjeux
411419c361 Community round-up #10 2013-11-06 12:44:42 -08:00
Ben Alpert
fc67d5544c Use smaller blog images and host directly 2013-11-06 12:44:25 -08:00
Andrey Popp
4faad1a32a "Thinking in React": fix list formatting 2013-11-05 16:16:18 -08:00
Paul O’Shannessy
01b40d84c7 Move header link styling out of documentation only
It's used in blog posts too. I also constrained it to just the anchor
class to avoid any other headers we have.
2013-11-05 15:06:58 -08:00
Paul O’Shannessy
67d0f15d1a Remove jQuery version number from tutorial docs 2013-11-05 14:42:46 -08:00
Ben Alpert
e5f03ae407 tutorial: Simplify ajax options
dataType was unnecessary; mimeType was both unnecessary and wrong in this case. Also removed an unnecessary bind and changed pollInterval to 2000 ms for consistency with https://github.com/petehunt/react-tutorial (faster is nicer if you actually try it out!).
2013-11-05 14:42:46 -08:00
Pete Hunt
25140e5a0d "Thinking in React" blog post 2013-11-05 14:41:15 -08:00
Paul O’Shannessy
b5804fa565 [docs] Clarify when getInitialState is called. 2013-11-04 17:21:56 -08:00
petehunt
1bb2651660 Update tutorial to use className 2013-11-04 17:21:28 -08:00
Ben Alpert
b21cdac9e3 Move heading anchors 50px up to avoid nav bar
Fixes #447.

We do this by moving the actual anchored element up in the page without moving the actual text. (Apple uses a similar trick in their framed docs.) Now this looks a bit sillier on smaller screens but it's better overall.
2013-11-04 17:21:16 -08:00
Paul O’Shannessy
92ce80cf4f blog post for 0.5.1 2013-10-29 12:52:00 -07:00
Paul O’Shannessy
f3db0006e8 Update everything for v0.5.1 2013-10-29 11:46:46 -07:00
Paul O’Shannessy
ef4d7a37f0 npm shrinkwrap
We should be doing this in the stable branch to ensure fuzzy
dependencies are met identically on subsequent releases.

In this case, browserify had a change in 2.34.3 which resulted in
JSXTransformer to be a different size. While it was a change for the
better, it was unexpected and not a change we were calling out in the
release.

This shrinkwraps to the same versions of packages we had when we shipped
0.5.0.
2013-10-29 11:46:46 -07:00
Laurence Rowe
64016811d3 Make 'disabled' MUST_USE_ATTRIBUTE for compatibility with CSS [disabled] selectors.
When a ReactDOMComponent is created with the property `disabled: true` subsequently setting the property to `disabled: false` the HTML attribute `disabled="true"` was being left in the DOM.
2013-10-29 10:16:04 -07:00
Andrey Popp
7b957c880c Fix unmounting components mounted into doc element
If we are to unmount a component mounted into a document element we should
unmount it from document.documentElement and not from document.firstChild which
is a doctype element in this specific case.
2013-10-29 10:16:04 -07:00
Ian Obermiller
1b835fb5cf Fix ReactTransitionEvents detectEvents 2013-10-29 10:16:04 -07:00
Cat Chen
9f0bbce797 fixed %d in invariant call 2013-10-29 10:16:04 -07:00
Josh Duck
c9d20e56d3 Don't reset mouseDown in focus handlers
Focus fires after mouse down on initial click, so we lost the
flag when the user initially began dragging on the input.
2013-10-29 10:16:04 -07:00
Ben Alpert
ce612904ef Make SelectEventPlugin not throw for range inputs
Accessing .selectionStart on a non-text input will throw (see http://www.w3.org/TR/2009/WD-html5-20090423/editing.html#textFieldSelection), so check that the input has selection capabilities before accessing the property.

Fixes #437.
2013-10-29 10:16:04 -07:00
Paul O’Shannessy
ea1ab5501d Update API docs for unmountAndReleaseReactRootNode 2013-10-26 17:45:03 -07:00
Brian Rue
2c35ed8068 ReactTransitionGroup example: fix typo and logic bug in handleRemove 2013-10-25 18:25:14 -07:00
Keito Uchiyama
c994cc24c3 docs: Delete Mutation Events (onCharacterDOMModified) 2013-10-25 18:24:37 -07:00
Paul O’Shannessy
24da1c0023 docs: remove OUTLINE 2013-10-21 15:20:46 -07:00
Cheng Lou
d82181e4b9 Add clickable anchors to docs headers
Closes #434
2013-10-21 14:38:57 -07:00
Paul O’Shannessy
ba166b9652 Fix live editor examples on home page.
Remember that one time I wrote release notes and said:

> This is a breaking change - if you were using class, you must change
> this to className or your components will be visually broken.

Good thing I didn't listen to myself!
2013-10-16 18:11:10 -07:00
Paul O’Shannessy
f756cb3d9c 0.5.0 release
Updated README, CHANGELOG, blog post
2013-10-16 11:44:37 -07:00
Paul O’Shannessy
cadf8b786c Fix grunt npm:test 2013-10-16 11:44:37 -07:00
Paul O’Shannessy
953947a617 bump version for 0.5 2013-10-15 22:32:20 -07:00
422 changed files with 9413 additions and 17699 deletions

View File

@@ -2,13 +2,11 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
max_line_length = 80
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
[*.md]
max_line_length = 0
trim_trailing_whitespace = false

1
.gitattributes vendored
View File

@@ -1 +0,0 @@
* text=auto

4
.gitignore vendored
View File

@@ -16,6 +16,4 @@ docs/css/react.css
docs/js/*
docs/downloads
examples/shared/*.js
test/the-files-to-test.generated.js
*.log*
chrome-user-data

View File

@@ -13,7 +13,6 @@
"noempty": true,
"nonstandard": true,
"onecase": true,
"sub": true,
"regexdash": true,
"trailing": true,
"undef": true,

View File

@@ -1,45 +1,21 @@
Ben Newman <bn@cs.stanford.edu> <benjamn@fb.com>
Cheng Lou <chenglou92@gmail.com> <chenglou@fb.com>
Christoph Pojer <christoph.pojer@gmail.com>
Christoph Pojer <christoph.pojer@gmail.com> <cpojer@fb.com>
Connor McSheffrey <c@conr.me> <connor.mcsheffrey@gmail.com>
Dan Schafer <dschafer@fb.com>
Evan Coonrod <evan@paloalto.com>
Fabio M. Costa <fabiomcosta@gmail.com> <fabs@fb.com>
Harry Hull <harry.hull1@gmail.com>
Ingvar Stepanyan <me@rreverser.com> <rreverser@ubuntu.rreverser.a4.internal.cloudapp.net>
Jaime Mingo <j.mingov@3boll.com>
Jason Bonta <jbonta@gmail.com> <jasonbonta@fb.com>
Jason Trill <jason@jasontrill.com>
Jeff Morrison <jeff@anafx.com> <Jeff@anafx.com>
Jeff Morrison <jeff@anafx.com> <jeffmo@fb.com>
Jeff Morrison <jeff@anafx.com> JeffMo <jeffmo@fb.com>
Jeffrey Lin <lin.jeffrey@gmail.com> <jeffreylin@fb.com>
Jonathan Hsu <jhiswin@gmail.com>
Jordan Walke <jordojw@gmail.com>
Jordan Walke <jordojw@gmail.com> <jordanjcw@fb.com>
Josh Duck <josh@fb.com> <github@joshduck.com>
Jun Wu <quark@lihdd.net>
Keito Uchiyama <projects@keito.me> <keito@fb.com>
Kunal Mehta <k.mehta@berkeley.edu> <kunalm@fb.com>
Laurence Rowe <l@lrowe.co.uk> <laurence@lrowe.co.uk>
Martin Andert <mandert@gmail.com>
Michal Srb <xixixao@seznam.cz> xixixao <xixixao@seznam.cz>
Nick Gavalas <njg57@cornell.edu>
Nick Thompson <ncthom91@gmail.com> <nickt@instagram.com>
Paul OShannessy <paul@oshannessy.com> <poshannessy@fb.com>
Paul Shen <paul@mnml0.com> <paulshen@fb.com>
Pete Hunt <floydophone@gmail.com>
Pete Hunt <floydophone@gmail.com> <pete.hunt@fb.com>
Pete Hunt <floydophone@gmail.com> <pete@instagram.com>
Pete Hunt <floydophone@gmail.com> <phunt@instagram.com>
Petri Lievonen <plievone@cc.hut.fi>
Pieter Vanderwerff <me@pieter.io> <pieter@heyday.co.nz>
Richard Feldman <richard.t.feldman@gmail.com> <richard@noredink.com>
Richard Livesey <Livesey7@hotmail.co.uk>
Sander Spies <sandermail@gmail.com>
Sebastian Markbåge <sebastian@calyptus.eu> <sema@fb.com>
Stoyan Stefanov <ssttoo@ymail.com>
Thomas Aylott <oblivious@subtlegradient.com> <aylott@fb.com>
Timothy Yung <yungsters@gmail.com> <yungsters@fb.com>
Vjeux <vjeuxx@gmail.com>
Vjeux <vjeuxx@gmail.com> <vjeux@fb.com>

View File

@@ -2,62 +2,14 @@
language: node_js
node_js:
- '0.10'
script:
- |
grunt $TEST_TYPE
after_script:
- |
if [ "$TEST_TYPE" = test:full ] && [ "$SERVER" ]; then
grunt build
curl \
-F "react=@build/react.js" \
-F "react.min=@build/react.min.js" \
-F "transformer=@build/JSXTransformer.js" \
-F "react-with-addons=@build/react-with-addons.js" \
-F "react-with-addons.min=@build/react-with-addons.min.js" \
-F "npm-react=@build/react.tgz" \
-F "npm-react-tools=@build/react-tools.tgz" \
-F "commit=$TRAVIS_COMMIT" \
-F "date=`git log --format='%ct' -1`" \
-F "pull_request=$TRAVIS_PULL_REQUEST" \
-F "token=$SECRET_TOKEN" \
-F "branch=$TRAVIS_BRANCH" \
$SERVER
fi
- curl -F "react=@build/react.js" -F "react.min=@build/react.min.js" -F "transformer=@build/JSXTransformer.js"
-F "react-with-addons=@build/react-with-addons.js" -F "react-with-addons.min=@build/react-with-addons.min.js"
-F "commit=$TRAVIS_COMMIT" -F "date=`git log --format='%ct' -1`" -F "pull_request=$TRAVIS_PULL_REQUEST"
-F "token=$SECRET_TOKEN" -F "branch=$TRAVIS_BRANCH" $SERVER
env:
matrix:
- TEST_TYPE=test:full
- TEST_TYPE=lint
- TEST_TYPE=perf:full
- TEST_TYPE=test:coverage
- TEST_TYPE=test:webdriver:saucelabs BROWSER_NAME=ie11
- TEST_TYPE=test:webdriver:saucelabs BROWSER_NAME=ie10
- TEST_TYPE=test:webdriver:saucelabs BROWSER_NAME=ie9
- TEST_TYPE=test:webdriver:saucelabs BROWSER_NAME=ie8
- TEST_TYPE=test:webdriver:saucelabs:ios
- TEST_TYPE=test:webdriver:saucelabs BROWSER_NAME=safari
global:
# SERVER
- secure: qPvsJ46XzGrdIuPA70b55xQNGF8jcK7N1LN5CCQYYocXLa+fBrl+fTE77QvehOPhqwJXcj6kOxI+sY0KrVwV7gmq2XY2HZGWUSCxTN0SZlNIzqPA80Y7G/yOjA4PUt8LKgP+8tptyhTAY56qf+hgW8BoLiKOdztYF2p+3zXOLuA=
# SECRET_TOKEN
- secure: dkpPW+VnoqC/okhRdV90m36NcyBFhcwEKL3bNFExAwi0dXnFao8RoFlvnwiPlA23h2faROkMIetXlti6Aju08BgUFV+f9aL6vLyU7gUent4Nd3413zf2fwDtXIWIETg6uLnOpSykGKgCAT/hY3Q2oPLqOoY0OxfgnbqwxkxljrE=
matrix:
fast_finish: true
allow_failures:
- env: TEST_TYPE=lint
- env: TEST_TYPE=test:coverage
- env: TEST_TYPE=perf:full
- env: TEST_TYPE=test:webdriver:saucelabs BROWSER_NAME=ie11
- env: TEST_TYPE=test:webdriver:saucelabs BROWSER_NAME=ie10
- env: TEST_TYPE=test:webdriver:saucelabs BROWSER_NAME=ie9
- env: TEST_TYPE=test:webdriver:saucelabs BROWSER_NAME=ie8
- env: TEST_TYPE=test:webdriver:saucelabs:ios
- env: TEST_TYPE=test:webdriver:saucelabs BROWSER_NAME=safari
notifications:
irc:
use_notice: true
skip_join: true
on_success: change
on_failure: change
channels:
- chat.freenode.net#reactjs

65
AUTHORS
View File

@@ -1,121 +1,66 @@
Adam Solove <asolove@gmail.com>
Alan deLevie <adelevie@gmail.com>
Alex Zelenskiy <azelenskiy@fb.com>
Alexander Solovyov <alexander@solovyov.net>
Andreas Svensson <andreas@syranide.com>
Andrew Davey <andrew@equin.co.uk>
Andrew Zich <azich@fb.com>
Andrey Popp <8mayday@gmail.com>
Ayman Osman <aymano.osman@gmail.com>
Ben Alpert <spicyjalapeno@gmail.com>
Ben Newman <bn@cs.stanford.edu>
Ben Ripkens <bripkens.dev@gmail.com>
Bob Eagan <bob@synapsestudios.com>
Brian Cooke <bri@bricooke.com>
Brian Kim <briankimpossible@gmail.com>
Brian Rue <brian@rollbar.com>
Cam Spiers <camspiers@gmail.com>
Cat Chen <catchen@fb.com>
Cheng Lou <chenglou92@gmail.com>
Christian Roman <chroman16@gmail.com>
Christoph Pojer <christoph.pojer@gmail.com>
Christoph Pojer <cpojer@fb.com>
Clay Allsopp <clay.allsopp@gmail.com>
Connor McSheffrey <c@conr.me>
Connor McSheffrey <connor.mcsheffrey@gmail.com>
Dan Schafer <dschafer@fb.com>
Daniel Gasienica <dgasienica@zynga.com>
Daniel Lo Nigro <danlo@fb.com>
Daniel Miladinov <dmiladinov@wingspan.com>
Danny Ben-David <dannybd@fb.com>
Daryl Lau <daryl@weak.io>
David Hellsing <david@aino.se>
David Hu <davidhu91@gmail.com>
Dustin Getz <dgetz@wingspan.com>
Eric Clemmons <eric@smarterspam.com>
Eric Florenzano <floguy@gmail.com>
Eric Schoffstall <contra@wearefractal.com>
Evan Coonrod <evan@paloalto.com>
Fabio M. Costa <fabiomcosta@gmail.com>
Felipe Oliveira Carvalho <felipekde@gmail.com>
Felix Kling <fkling@fb.com>
Fernando Correia <fernando@servicero.com>
Greg Hurrell <glh@fb.com>
Greg Roodt <groodt@gmail.com>
Guido Bouman <m@guido.vc>
Harry Hull <harry.hull1@gmail.com>
Hugo Jobling <me@thisishugo.com>
Ian Obermiller <iano@fb.com>
Ingvar Stepanyan <me@rreverser.com>
Isaac Salier-Hellendag <isaac@fb.com>
Ivan Kozik <ivan@ludios.org>
Jaime Mingo <j.mingov@3boll.com>
Jakub Malinowski <jakubmal@gmail.com>
James Ide <ide@fb.com>
Jamie Wong <jamie.lf.wong@gmail.com>
Jamison Dance <jergason@gmail.com>
Jan Kassens <jkassens@fb.com>
Jared Forsyth <jared@jaredforsyth.com>
Jason Bonta <jbonta@gmail.com>
Jason Trill <jason@jasontrill.com>
Jean Lauliac <lauliacj@gmail.com>
Jeff Barczewski <jeff.barczewski@gmail.com>
Jeff Carpenter <gcarpenterv@gmail.com>
Jeff Morrison <jeff@anafx.com>
Jeffrey Lin <lin.jeffrey@gmail.com>
Jignesh Kakadiya <jigneshhk1992@gmail.com>
Jing Chen <jingc@fb.com>
Johannes Baiter <johannes.baiter@gmail.com>
John Watson <jwatson@fb.com>
Jonas Gebhardt <jonas@instagram.com>
Jonathan Hsu <jhiswin@gmail.com>
Jordan Walke <jordojw@gmail.com>
Josh Duck <josh@fb.com>
Jun Wu <quark@lihdd.net>
Keito Uchiyama <projects@keito.me>
Kit Randel <kit@nocturne.net.nz>
Keito Uchiyama <keito@fb.com>
Kunal Mehta <k.mehta@berkeley.edu>
Laurence Rowe <l@lrowe.co.uk>
Levi McCallum <levi@levimccallum.com>
Lily <qvang.j@gmail.com>
Logan Allen <loganfynne@gmail.com>
Luigy Leon <luichi.19@gmail.com>
Mark Richardson <echo@fb.com>
Marshall Roch <mroch@fb.com>
Martin Andert <mandert@gmail.com>
Martin Konicek <mkonicek@fb.com>
Mathieu M-Gosselin <mathieumg@gmail.com>
Matt Harrison <mt.harrison86@gmail.com>
Matti Nelimarkka <matti.nelimarkka@hiit.fi>
Michal Srb <xixixao@seznam.cz>
Mouad Debbar <mdebbar@fb.com>
Nadeesha Cabral <nadeesha.cabral@gmail.com>
Nicholas Bergson-Shilcock <me@nicholasbs.net>
Nick Gavalas <njg57@cornell.edu>
Nick Thompson <ncthom91@gmail.com>
Owen Coutts <owenc@fb.com>
Pascal Hartig <passy@twitter.com>
Paul OShannessy <paul@oshannessy.com>
Paul Seiffert <paul.seiffert@gmail.com>
Paul Shen <paul@mnml0.com>
Pete Hunt <floydophone@gmail.com>
Peter Cottle <pcottle@fb.com>
Petri Lievonen <plievone@cc.hut.fi>
Pieter Vanderwerff <me@pieter.io>
Richard D. Worth <rdworth@gmail.com>
Richard Feldman <richard.t.feldman@gmail.com>
Richard Livesey <Livesey7@hotmail.co.uk>
Pieter Vanderwerff <pieter@heyday.co.nz>
Sander Spies <sandermail@gmail.com>
Sean Kinsey <oyvind@fb.com>
Sebastian Markbåge <sebastian@calyptus.eu>
Shaun Trennery <shaun.trennery@gmail.com>
Simon Højberg <r.hackr@gmail.com>
Stoyan Stefanov <ssttoo@ymail.com>
Sundeep Malladi <sundeep.malladi@gmail.com>
Thomas Aylott <oblivious@subtlegradient.com>
Thomas Aylott <aylott@fb.com>
Timothy Yung <yungsters@gmail.com>
Tom Occhino <tomocchino@gmail.com>
Ville Immonen <ville.immonen@iki.fi>
Vjeux <vjeuxx@gmail.com>
Wincent Colaiuta <win@wincent.com>
Zach Bruggeman <zbruggeman@me.com>
fxbois <fxbois@gmail.com>
imagentleman <imagentlemail@gmail.com>

View File

@@ -1,85 +1,3 @@
## 0.9.0 (February 20, 2014)
### React Core
#### Breaking Changes
- The lifecycle methods `componentDidMount` and `componentDidUpdate` no longer receive the root node as a parameter; use `this.getDOMNode()` instead
- Whenever a prop is equal to `undefined`, the default value returned by `getDefaultProps` will now be used instead
- `React.unmountAndReleaseReactRootNode` was previously deprecated and has now been removed
- `React.renderComponentToString` is now synchronous and returns the generated HTML string
- Full-page rendering (that is, rendering the `<html>` tag using React) is now supported only when starting with server-rendered markup
- On mouse wheel events, `deltaY` is no longer negated
- When prop types validation fails, a warning is logged instead of an error thrown (with the production build of React, type checks are now skipped for performance)
- On `input`, `select`, and `textarea` elements, `.getValue()` is no longer supported; use `.getDOMNode().value` instead
- `this.context` on components is now reserved for internal use by React
#### New Features
- React now never rethrows errors, so stack traces are more accurate and Chrome's purple break-on-error stop sign now works properly
- Added support for SVG tags `defs`, `linearGradient`, `polygon`, `radialGradient`, `stop`
- Added support for more attributes:
- `crossOrigin` for CORS requests
- `download` and `hrefLang` for `<a>` tags
- `mediaGroup` and `muted` for `<audio>` and `<video>` tags
- `noValidate` and `formNoValidate` for forms
- `property` for Open Graph `<meta>` tags
- `sandbox`, `seamless`, and `srcDoc` for `<iframe>` tags
- `scope` for screen readers
- `span` for `<colgroup>` tags
- Added support for defining `propTypes` in mixins
- Added `any`, `arrayOf`, `component`, `oneOfType`, `renderable`, `shape` to `React.PropTypes`
- Added support for `statics` on component spec for static component methods
- On all events, `.currentTarget` is now properly set
- On keyboard events, `.key` is now polyfilled in all browsers for special (non-printable) keys
- On clipboard events, `.clipboardData` is now polyfilled in IE
- On drag events, `.dragTransfer` is now present
- Added support for `onMouseOver` and `onMouseOut` in addition to the existing `onMouseEnter` and `onMouseLeave` events
- Added support for `onLoad` and `onError` on `<img>` elements
- Added support for `onReset` on `<form>` elements
- The `autoFocus` attribute is now polyfilled consistently on `input`, `select`, and `textarea`
#### Bug Fixes
- React no longer adds an `__owner__` property to each component's `props` object; passed-in props are now never mutated
- When nesting top-level components (e.g., calling `React.renderComponent` within `componentDidMount`), events now properly bubble to the parent component
- Fixed a case where nesting top-level components would throw an error when updating
- Passing an invalid or misspelled propTypes type now throws an error
- On mouse enter/leave events, `.target`, `.relatedTarget`, and `.type` are now set properly
- On composition events, `.data` is now properly normalized in IE9 and IE10
- CSS property values no longer have `px` appended for the unitless properties `columnCount`, `flex`, `flexGrow`, `flexShrink`, `lineClamp`, `order`, `widows`
- Fixed a memory leak when unmounting children with a `componentWillUnmount` handler
- Fixed a memory leak when `renderComponentToString` would store event handlers
- Fixed an error that could be thrown when removing form elements during a click handler
- Boolean attributes such as `disabled` are rendered without a value (previously `disabled="true"`, now simply `disabled`)
- `key` values containing `.` are now supported
- Shortened `data-reactid` values for performance
- Components now always remount when the `key` property changes
- Event handlers are attached to `document` only when necessary, improving performance in some cases
- Events no longer use `.returnValue` in modern browsers, eliminating a warning in Chrome
- `scrollLeft` and `scrollTop` are no longer accessed on document.body, eliminating a warning in Chrome
- General performance fixes, memory optimizations, improvements to warnings and error messages
### React with Addons
- `React.addons.TestUtils` was added to help write unit tests
- `React.addons.TransitionGroup` was renamed to `React.addons.CSSTransitionGroup`
- `React.addons.TransitionGroup` was added as a more general animation wrapper
- `React.addons.cloneWithProps` was added for cloning components and modifying their props
- Bug fix for adding back nodes during an exit transition for CSSTransitionGroup
- Bug fix for changing `transitionLeave` in CSSTransitionGroup
- Performance optimizations for CSSTransitionGroup
- On checkbox `<input>` elements, `checkedLink` is now supported for two-way binding
### JSX Compiler and react-tools Package
- Whitespace normalization has changed; now space between two tags on the same line will be preserved, while newlines between two tags will be removed
- The `react-tools` npm package no longer includes the React core libraries; use the `react` package instead.
- `displayName` is now added in more cases, improving error messages and names in the React Dev Tools
- Fixed an issue where an invalid token error was thrown after a JSX closing tag
- `JSXTransformer` now uses source maps automatically in modern browsers
- `JSXTransformer` error messages now include the filename and problematic line contents when a file fails to parse
## 0.8.0 (December 19, 2013)
### React

View File

@@ -57,7 +57,6 @@ Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe
* `"use strict";`
* 80 character line length
* "Attractive"
* Do not use the optional parameters of `setTimeout` and `setInterval`
## License

View File

@@ -3,206 +3,116 @@
var exec = require('child_process').exec;
var jsxTask = require('./grunt/tasks/jsx');
var browserifyTask = require('./grunt/tasks/browserify');
var wrapupTask = require('./grunt/tasks/wrapup');
var populistTask = require('./grunt/tasks/populist');
var webdriverPhantomJSTask = require('./grunt/tasks/webdriver-phantomjs');
var webdriverJasmineTasks = require('./grunt/tasks/webdriver-jasmine');
var sauceTunnelTask = require('./grunt/tasks/sauce-tunnel');
var phantomTask = require('./grunt/tasks/phantom');
var npmTask = require('./grunt/tasks/npm');
var releaseTasks = require('./grunt/tasks/release');
var npmReactTasks = require('./grunt/tasks/npm-react');
var npmReactToolsTasks = require('./grunt/tasks/npm-react-tools');
var versionCheckTask = require('./grunt/tasks/version-check');
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
copy: require('./grunt/config/copy'),
jsx: require('./grunt/config/jsx'),
jsx: require('./grunt/config/jsx/jsx'),
browserify: require('./grunt/config/browserify'),
wrapup: require('./grunt/config/wrapup'),
populist: require('./grunt/config/populist'),
connect: require('./grunt/config/server')(grunt),
"webdriver-jasmine": require('./grunt/config/webdriver-jasmine'),
"webdriver-perf": require('./grunt/config/webdriver-perf'),
phantom: require('./grunt/config/phantom'),
npm: require('./grunt/config/npm'),
clean: ['./build', './*.gem', './docs/_site', './examples/shared/*.js', '.module-cache'],
clean: ['./build', './*.gem', './docs/_site', './examples/shared/*.js'],
jshint: require('./grunt/config/jshint'),
compare_size: require('./grunt/config/compare_size'),
complexity: require('./grunt/config/complexity')
compare_size: require('./grunt/config/compare_size')
});
grunt.config.set('compress', require('./grunt/config/compress'));
Object.keys(grunt.file.readJSON('package.json').devDependencies)
.filter(function(npmTaskName) { return npmTaskName.indexOf('grunt-') === 0; })
.filter(function(npmTaskName) { return npmTaskName != 'grunt-cli'; })
.forEach(function(npmTaskName) { grunt.loadNpmTasks(npmTaskName); });
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-compare-size');
grunt.loadNpmTasks('grunt-contrib-compress');
// Alias 'jshint' to 'lint' to better match the workflow we know
grunt.registerTask('lint', ['jshint']);
grunt.registerTask('download-previous-version', require('./grunt/tasks/download-previous-version.js'));
grunt.registerTask('delete-build-modules', function() {
if (grunt.file.exists('build/modules')) {
grunt.file.delete('build/modules');
}
});
// Register jsx:normal and :release tasks.
// Register jsx:debug and :release tasks.
grunt.registerMultiTask('jsx', jsxTask);
// Our own browserify-based tasks to build a single JS file build
grunt.registerMultiTask('browserify', browserifyTask);
// Similar to Browserify, use WrapUp to generate single JS file that
// defines global variables instead of using require.
grunt.registerMultiTask('wrapup', wrapupTask);
grunt.registerMultiTask('populist', populistTask);
grunt.registerTask('sauce-tunnel', sauceTunnelTask);
grunt.registerMultiTask('webdriver-jasmine', webdriverJasmineTasks);
grunt.registerMultiTask('webdriver-perf', require('./grunt/tasks/webdriver-perf'));
grunt.registerMultiTask('phantom', phantomTask);
grunt.registerMultiTask('npm', npmTask);
grunt.registerTask('npm-react:release', npmReactTasks.buildRelease);
grunt.registerTask('npm-react:pack', npmReactTasks.packRelease);
grunt.registerTask('npm-react-tools:pack', npmReactToolsTasks.pack);
grunt.registerTask('version-check', versionCheckTask);
// Check that the version we're exporting is the same one we expect in the
// package. This is not an ideal way to do this, but makes sure that we keep
// them in sync.
var reactVersionExp = /\bReact\.version\s*=\s*['"]([^'"]+)['"];/;
grunt.registerTask('version-check', function() {
var reactVersion = reactVersionExp.exec(
grunt.file.read('./build/modules/React.js')
)[1];
var npmReactVersion = grunt.file.readJSON('./npm-react/package.json').version;
var reactToolsVersion = grunt.config.data.pkg.version;
grunt.registerTask('build:basic', ['jsx:normal', 'version-check', 'browserify:basic']);
grunt.registerTask('build:addons', ['jsx:normal', 'browserify:addons']);
grunt.registerTask('build:transformer', ['jsx:normal', 'browserify:transformer']);
grunt.registerTask('build:min', ['jsx:normal', 'version-check', 'browserify:min']);
grunt.registerTask('build:addons-min', ['jsx:normal', 'browserify:addonsMin']);
grunt.registerTask('build:withCodeCoverageLogging', [
'jsx:normal',
'version-check',
'browserify:withCodeCoverageLogging'
]);
grunt.registerTask('build:perf', [
'jsx:normal',
'version-check',
'browserify:transformer',
'browserify:basic',
'browserify:min',
'download-previous-version'
]);
grunt.registerTask('build:test', [
'delete-build-modules',
'jsx:test',
'version-check',
'populist:test'
]);
grunt.registerTask('build:npm-react', ['version-check', 'jsx:normal', 'npm-react:release']);
grunt.registerTask('webdriver-phantomjs', webdriverPhantomJSTask);
grunt.registerTask('coverage:parse', require('./grunt/tasks/coverage-parse'));
grunt.registerTask('test:webdriver:phantomjs', [
'connect',
'webdriver-phantomjs',
'webdriver-jasmine:local'
]);
grunt.registerTask('perf:webdriver:phantomjs', [
'connect',
'webdriver-phantomjs',
'webdriver-perf:local'
]);
grunt.registerTask('test:full', [
'build:test',
'build:basic',
'connect',
'webdriver-phantomjs',
'webdriver-jasmine:local',
'sauce-tunnel',
'webdriver-jasmine:saucelabs_android',
'webdriver-jasmine:saucelabs_firefox',
'webdriver-jasmine:saucelabs_chrome'
]);
grunt.registerTask('perf:full', [
'build:perf',
'connect',
'webdriver-phantomjs',
'webdriver-perf:local',
'sauce-tunnel',
'webdriver-perf:saucelabs_firefox',
'webdriver-perf:saucelabs_chrome',
'webdriver-perf:saucelabs_ie11',
'webdriver-perf:saucelabs_ie8',
]);
grunt.registerTask('test:webdriver:saucelabs', [
'build:test',
'build:basic',
'connect',
'sauce-tunnel',
'webdriver-jasmine:saucelabs_' + (process.env.BROWSER_NAME || 'ie8')
]);
grunt.registerTask('test:webdriver:saucelabs:ie', [
'build:test',
'build:basic',
'connect',
'sauce-tunnel',
'webdriver-jasmine:saucelabs_ie8',
'webdriver-jasmine:saucelabs_ie9',
'webdriver-jasmine:saucelabs_ie10',
'webdriver-jasmine:saucelabs_ie11'
]);
grunt.registerTask('test:webdriver:saucelabs:ios', [
'build:test',
'build:basic',
'connect',
'sauce-tunnel',
'webdriver-jasmine:saucelabs_ios6_1',
'webdriver-jasmine:saucelabs_ios5_1',
'webdriver-jasmine:saucelabs_ios4'
]);
grunt.registerTask('test:coverage', [
'build:test',
'build:withCodeCoverageLogging',
'test:webdriver:phantomjs',
'coverage:parse'
]);
grunt.registerTask('test', function() {
if (grunt.option('debug')) {
grunt.task.run('build:test', 'build:basic', 'connect:server:keepalive');
} else {
grunt.task.run('build:test', 'build:basic', 'test:webdriver:phantomjs');
if (reactVersion !== reactToolsVersion) {
grunt.log.error(
'React version does not match react-tools version. Expected %s, saw %s',
reactToolsVersion,
reactVersion
);
return false;
}
if (npmReactVersion !== reactToolsVersion) {
grunt.log.error(
'npm-react version does not match react-tools veersion. Expected %s, saw %s',
reactToolsVersion,
npmReactVersion
);
return false;
}
});
grunt.registerTask('perf', ['build:perf', 'perf:webdriver:phantomjs']);
grunt.registerTask('build:basic', ['jsx:debug', 'version-check', 'browserify:basic']);
grunt.registerTask('build:addons', ['jsx:debug', 'browserify:addons']);
grunt.registerTask('build:transformer', ['jsx:debug', 'browserify:transformer']);
grunt.registerTask('build:min', ['jsx:release', 'version-check', 'browserify:min']);
grunt.registerTask('build:addons-min', ['jsx:debug', 'browserify:addonsMin']);
grunt.registerTask('build:test', [
'jsx:jasmine',
'jsx:test',
'version-check',
'populist:jasmine',
'populist:test'
]);
grunt.registerTask('build:npm-react', ['version-check', 'jsx:release', 'npm-react:release']);
grunt.registerTask('test', ['build:test', 'build:basic', 'phantom:run']);
grunt.registerTask('npm:test', ['build', 'npm:pack']);
// Optimized build task that does all of our builds. The subtasks will be run
// in order so we can take advantage of that and only run jsx:normal once.
// in order so we can take advantage of that and only run jsx:debug once.
grunt.registerTask('build', [
'delete-build-modules',
'jsx:normal',
'jsx:debug',
'version-check',
'browserify:basic',
'browserify:transformer',
'browserify:addons',
'jsx:release',
'browserify:min',
'browserify:addonsMin',
'npm-react:release',
'npm-react:pack',
'npm-react-tools:pack',
'copy:react_docs',
'compare_size'
]);

View File

@@ -10,7 +10,7 @@ React is a JavaScript library for building user interfaces.
## The `react` npm package has recently changed!
If you're looking for jeffbski's [React.js](https://github.com/jeffbski/autoflow) project, it's now in `npm` as `autoflow` rather than `react`.
If you're looking for jeffbski's [React.js](https://github.com/jeffbski/react) project, it's now in `npm` as `reactjs` rather than `react`.
## Examples
@@ -32,7 +32,7 @@ React.renderComponent(
This example will render "Hello John" into a container on the page.
You'll notice that we used an HTML-like syntax; [we call it JSX](http://facebook.github.io/react/docs/jsx-in-depth.html). JSX is not required to use React, but it makes code more readable, and writing it feels like writing HTML. A simple transform is included with React that allows converting JSX into native JavaScript for browsers to digest.
You'll notice that we used an XML-like syntax; [we call it JSX](http://facebook.github.io/react/docs/jsx-in-depth.html). JSX is not required to use React, but it makes code more readable, and writing it feels like writing HTML. A simple transform is included with React that allows converting JSX into native JavaScript for browsers to digest.
## Installation
@@ -40,12 +40,12 @@ The fastest way to get started is to serve JavaScript from the CDN (also availab
```html
<!-- The core React library -->
<script src="http://fb.me/react-0.9.0.js"></script>
<script src="http://fb.me/react-0.8.0.js"></script>
<!-- In-browser JSX transformer, remove when pre-compiling JSX. -->
<script src="http://fb.me/JSXTransformer-0.9.0.js"></script>
<script src="http://fb.me/JSXTransformer-0.8.0.js"></script>
```
We've also built a [starter kit](http://facebook.github.io/react/downloads/react-0.9.0.zip) which might be useful if this is your first time using React. It includes a webpage with an example of using React with live code.
We've also built a [starter kit](http://facebook.github.io/react/downloads/react-0.8.0.zip) which might be useful if this is your first time using React. It includes a webpage with an example of using React with live code.
If you'd like to use [bower](http://bower.io), it's as easy as:
@@ -87,8 +87,6 @@ We use grunt to automate many tasks. Run `grunt -h` to see a mostly complete lis
```sh
# Build and run tests with PhantomJS
grunt test
# Build and run tests in your browser
grunt test --debug
# Lint the code with JSHint
grunt lint
# Wipe out build directory

20
bin/jsx
View File

@@ -1,24 +1,12 @@
#!/usr/bin/env node
// -*- mode: js -*-
"use strict";
var visitors = require('../vendor/fbtransform/visitors');
var visitors = require('../vendor/fbtransform/visitors').transformVisitors;
var transform = require('jstransform').transform;
require('commoner').version(
require('../package.json').version
).resolve(function(id) {
require("commoner").resolve(function(id) {
return this.readModuleP(id);
}).option(
'--harmony',
'Turns on JS transformations such as ES6 Classes etc.'
).process(function(id, source) {
}).process(function(id, source) {
// This is where JSX, ES6, etc. desugaring happens.
var visitorList;
if (this.options.harmony) {
visitorList = visitors.getAllVisitors();
} else {
visitorList = visitors.transformVisitors.react;
}
return transform(visitorList, source).code;
return transform(visitors.react, source).code;
});

View File

@@ -1,14 +1,11 @@
#!/usr/bin/env node
// -*- mode: js -*-
"use strict";
var getAllVisitors = require('../vendor/fbtransform/visitors').getAllVisitors;
var visitors = require('../vendor/fbtransform/visitors').transformVisitors;
var transform = require('jstransform').transform;
var propagate = require("../vendor/constants").propagate;
require("commoner").version(
require("../package.json").version
).resolve(function(id) {
require("commoner").resolve(function(id) {
var context = this;
// Note that the result of context.getProvidedP() is cached for the
@@ -31,7 +28,7 @@ require("commoner").version(
var constants = context.config.constants || {};
// This is where JSX, ES6, etc. desugaring happens.
source = transform(getAllVisitors(), source).code;
source = transform(visitors.react, source).code;
// Constant propagation means removing any obviously dead code after
// replacing constant expressions with literal (boolean) values.

View File

@@ -13,7 +13,7 @@ redcarpet:
pygments: true
name: React
markdown: redcarpet
react_version: 0.10.0-alpha
react_version: 0.8.0
description: A JavaScript library for building user interfaces
relative_permalinks: true
paginate: 5

View File

@@ -749,19 +749,3 @@ p code {
div[data-twttr-id] iframe {
margin: 10px auto !important;
}
/* Acknowledgements */
.three-column {
@include clearfix;
}
.three-column > ul {
float: left;
margin-left: 30px;
width: 190px;
}
.three-column > ul:first-child {
margin-left: 20px;
}

View File

@@ -4,16 +4,12 @@
title: Getting Started
- id: tutorial
title: Tutorial
- id: thinking-in-react
title: Thinking in React
- title: Community Resources
items:
- id: videos
title: Videos
- id: complementary-tools
title: Complementary Tools
- id: examples
title: Examples
title: Complementary tools
- id: example-apps
title: Example apps
- title: Guides
items:
- id: why-react
@@ -49,12 +45,8 @@
title: Two-Way Binding Helpers
- id: class-name-manipulation
title: Class Name Manipulation
- id: test-utils
title: Test Utilities
- id: clone-with-props
title: Cloning Components
- id: update
title: Immutability Helpers
- id: examples
title: Examples
- title: Reference
items:
- id: top-level-api
@@ -70,6 +62,6 @@
- id: dom-differences
title: DOM Differences
- id: special-non-dom-attributes
title: Special Non-DOM Attributes
title: Special Non-DOM attributes
- id: reconciliation
title: Reconciliation

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013-2014 Facebook, Inc.
* Copyright 2013 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013-2014 Facebook, Inc.
* Copyright 2013 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -21,7 +21,6 @@ React.renderComponent(
codeText={HELLO_COMPONENT}
renderCode={true}
transformer={transformer}
showCompiledJSTab={false}
/>,
/>,
document.getElementById('jsxCompiler')
);

View File

@@ -85,8 +85,7 @@ var ReactPlayground = React.createClass({
return {
transformer: function(code) {
return JSXTransformer.transform(code).code;
},
showCompiledJSTab: true
}
};
},
@@ -117,7 +116,7 @@ var ReactPlayground = React.createClass({
compiledCode = this.compileCode();
} catch (err) {}
var JSContent =
var jsContent =
<CodeMirrorEditor
key="js"
className="playgroundStage CodeMirror-readonly"
@@ -126,7 +125,7 @@ var ReactPlayground = React.createClass({
readOnly={true}
/>;
var JSXContent =
var jsxContent =
<CodeMirrorEditor
key="jsx"
onChange={this.handleCodeChange}
@@ -139,28 +138,22 @@ var ReactPlayground = React.createClass({
var JSTabClassName =
'playground-tab' + (isJS ? ' playground-tab-active' : '');
var JSTab =
<div
className={JSTabClassName}
onClick={this.handleCodeModeSwitch.bind(this, this.MODES.JS)}>
Compiled JS
</div>;
var JSXTab =
<div
className={JSXTabClassName}
onClick={this.handleCodeModeSwitch.bind(this, this.MODES.JSX)}>
Live JSX Editor
</div>
return (
<div className="playground">
<div>
{JSXTab}
{this.props.showCompiledJSTab && JSTab}
<div
className={JSXTabClassName}
onClick={this.handleCodeModeSwitch.bind(this, this.MODES.JSX)}>
Live JSX Editor
</div>
<div
className={JSTabClassName}
onClick={this.handleCodeModeSwitch.bind(this, this.MODES.JS)}>
Compiled JS
</div>
</div>
<div className="playgroundCode">
{isJS ? JSContent : JSXContent}
{isJS ? jsContent : jsxContent}
</div>
<div className="playgroundPreview">
<div ref="mount" />

View File

@@ -46,7 +46,7 @@
React
</a>
<ul class="nav-site">
<li><a href="/react/docs/getting-started.html"{% if page.sectionid == 'docs' or page.sectionid == 'tips' %} class="active"{% endif %}>docs</a></li>
<li><a href="/react/docs/getting-started.html"{% if page.sectionid == 'docs' %} class="active"{% endif %}>docs</a></li>
<li><a href="/react/support.html"{% if page.id == 'support' %} class="active"{% endif %}>support</a></li>
<li><a href="/react/downloads.html"{% if page.id == 'downloads' %} class="active"{% endif %}>download</a></li>
<li><a href="/react/blog/"{% if page.sectionid == 'blog' %} class="active"{% endif %}>blog</a></li>
@@ -74,10 +74,7 @@
{{ content }}
<footer class="wrap">
<div class="left">
A Facebook &amp; Instagram collaboration.<br>
<a href="/react/acknowledgements.html">Acknowledgements</a>
</div>
<div class="left">A Facebook &amp; Instagram collaboration.</div>
<div class="right">&copy; 2014 Facebook Inc.</div>
</footer>
</div>

View File

@@ -41,7 +41,7 @@ React really shines when your data changes over time.
In a traditional JavaScript application, you need to look at what data changed
and imperatively make changes to the DOM to keep it up-to-date. Even AngularJS,
which provides a declarative interface via directives and data binding [requires
a linking function to manually update DOM nodes](http://code.angularjs.org/1.0.8/docs/guide/directive#reasonsbehindthecompilelinkseparation).
a linking function to manually update DOM nodes](http://docs.angularjs.org/guide/directive#reasonsbehindthecompilelinkseparation).
React takes a different approach.

View File

@@ -68,7 +68,6 @@ In cases where you want to preserve the space adjacent to a newline, you can wri
- On mouse wheel events, `deltaY` is no longer negated
- When prop types validation fails, a warning is logged instead of an error thrown (with the production build of React, the type checks are now skipped for performance)
- On `input`, `select`, and `textarea` elements, `.getValue()` is no longer supported; use `.getDOMNode().value` instead
- `this.context` on components is now reserved for internal use by React
#### New Features
@@ -87,7 +86,7 @@ In cases where you want to preserve the space adjacent to a newline, you can wri
- On all events, `.currentTarget` is now properly set
- On keyboard events, `.key` is now polyfilled in all browsers for special (non-printable) keys
- On clipboard events, `.clipboardData` is now polyfilled in IE
- On drag events, `.dataTransfer` is now present
- On drag events, `.dragTransfer` is now present
- Added support for `onMouseOver` and `onMouseOut` in addition to the existing `onMouseEnter` and `onMouseLeave` events
- Added support for `onLoad` and `onError` on `<img>` elements
- Added support for `onReset` on `<form>` elements

View File

@@ -1,145 +0,0 @@
---
title: React v0.9
layout: post
author: Ben Alpert
---
I'm excited to announce that today we're releasing React v0.9, which incorporates many bug fixes and several new features since the last release. This release contains almost four months of work, including over 800 commits from over 70 committers!
Thanks to everyone who tested the release candidate; we were able to find and fix an error in the event handling code, we upgraded envify to make running browserify on React faster, and we added support for five new attributes.
As always, the release is available for download from the CDN:
* **React**
Dev build with warnings: <http://fb.me/react-0.9.0.js>
Minified build for production: <http://fb.me/react-0.9.0.min.js>
* **React with Add-Ons**
Dev build with warnings: <http://fb.me/react-with-addons-0.9.0.js>
Minified build for production: <http://fb.me/react-with-addons-0.9.0.min.js>
* **In-Browser JSX Transformer**
<http://fb.me/JSXTransformer-0.9.0.js>
We've also published version `0.9.0` of the `react` and `react-tools` packages on npm and the `react` package on bower.
## Whats New?
This version includes better support for normalizing event properties across all supported browsers so that you need to worry even less about cross-browser differences. We've also made many improvements to error messages and have refactored the core to never rethrow errors, so stack traces are more accurate and Chrome's purple break-on-error stop sign now works properly.
We've also added to the add-ons build [React.addons.TestUtils](/react/docs/test-utils.html), a set of new utilities to help you write unit tests for React components. You can now simulate events on your components, and several helpers are provided to help make assertions about the rendered DOM tree.
We've also made several other improvements and a few breaking changes; the full changelog is provided below.
## JSX Whitespace
In addition to the changes to React core listed below, we've made a small change to the way JSX interprets whitespace to make things more consistent. With this release, space between two components on the same line will be preserved, while a newline separating a text node from a tag will be eliminated in the output. Consider the code:
```html
<div>
Monkeys:
{listOfMonkeys} {submitButton}
</div>
```
In v0.8 and below, it was transformed to the following:
```javascript
React.DOM.div(null,
" Monkeys: ",
listOfMonkeys, submitButton
)
```
In v0.9, it will be transformed to this JS instead:
```javascript{2,3}
React.DOM.div(null,
"Monkeys:",
listOfMonkeys, " ", submitButton
)
```
We believe this new behavior is more helpful and elimates cases where unwanted whitespace was previously added.
In cases where you want to preserve the space adjacent to a newline, you can write `{'Monkeys: '}` or `Monkeys:{' '}` in your JSX source. We've included a script to do an automated codemod of your JSX source tree that preserves the old whitespace behavior by adding and removing spaces appropriately. You can [install jsx\_whitespace\_transformer from npm](https://github.com/facebook/react/blob/master/npm-jsx_whitespace_transformer/README.md) and run it over your source tree to modify files in place. The transformed JSX files will preserve your code's existing whitespace behavior.
## Changelog
### React Core
#### Breaking Changes
- The lifecycle methods `componentDidMount` and `componentDidUpdate` no longer receive the root node as a parameter; use `this.getDOMNode()` instead
- Whenever a prop is equal to `undefined`, the default value returned by `getDefaultProps` will now be used instead
- `React.unmountAndReleaseReactRootNode` was previously deprecated and has now been removed
- `React.renderComponentToString` is now synchronous and returns the generated HTML string
- Full-page rendering (that is, rendering the `<html>` tag using React) is now supported only when starting with server-rendered markup
- On mouse wheel events, `deltaY` is no longer negated
- When prop types validation fails, a warning is logged instead of an error thrown (with the production build of React, type checks are now skipped for performance)
- On `input`, `select`, and `textarea` elements, `.getValue()` is no longer supported; use `.getDOMNode().value` instead
- `this.context` on components is now reserved for internal use by React
#### New Features
- React now never rethrows errors, so stack traces are more accurate and Chrome's purple break-on-error stop sign now works properly
- Added support for SVG tags `defs`, `linearGradient`, `polygon`, `radialGradient`, `stop`
- Added support for more attributes:
- `crossOrigin` for CORS requests
- `download` and `hrefLang` for `<a>` tags
- `mediaGroup` and `muted` for `<audio>` and `<video>` tags
- `noValidate` and `formNoValidate` for forms
- `property` for Open Graph `<meta>` tags
- `sandbox`, `seamless`, and `srcDoc` for `<iframe>` tags
- `scope` for screen readers
- `span` for `<colgroup>` tags
- Added support for defining `propTypes` in mixins
- Added `any`, `arrayOf`, `component`, `oneOfType`, `renderable`, `shape` to `React.PropTypes`
- Added support for `statics` on component spec for static component methods
- On all events, `.currentTarget` is now properly set
- On keyboard events, `.key` is now polyfilled in all browsers for special (non-printable) keys
- On clipboard events, `.clipboardData` is now polyfilled in IE
- On drag events, `.dataTransfer` is now present
- Added support for `onMouseOver` and `onMouseOut` in addition to the existing `onMouseEnter` and `onMouseLeave` events
- Added support for `onLoad` and `onError` on `<img>` elements
- Added support for `onReset` on `<form>` elements
- The `autoFocus` attribute is now polyfilled consistently on `input`, `select`, and `textarea`
#### Bug Fixes
- React no longer adds an `__owner__` property to each component's `props` object; passed-in props are now never mutated
- When nesting top-level components (e.g., calling `React.renderComponent` within `componentDidMount`), events now properly bubble to the parent component
- Fixed a case where nesting top-level components would throw an error when updating
- Passing an invalid or misspelled propTypes type now throws an error
- On mouse enter/leave events, `.target`, `.relatedTarget`, and `.type` are now set properly
- On composition events, `.data` is now properly normalized in IE9 and IE10
- CSS property values no longer have `px` appended for the unitless properties `columnCount`, `flex`, `flexGrow`, `flexShrink`, `lineClamp`, `order`, `widows`
- Fixed a memory leak when unmounting children with a `componentWillUnmount` handler
- Fixed a memory leak when `renderComponentToString` would store event handlers
- Fixed an error that could be thrown when removing form elements during a click handler
- Boolean attributes such as `disabled` are rendered without a value (previously `disabled="true"`, now simply `disabled`)
- `key` values containing `.` are now supported
- Shortened `data-reactid` values for performance
- Components now always remount when the `key` property changes
- Event handlers are attached to `document` only when necessary, improving performance in some cases
- Events no longer use `.returnValue` in modern browsers, eliminating a warning in Chrome
- `scrollLeft` and `scrollTop` are no longer accessed on document.body, eliminating a warning in Chrome
- General performance fixes, memory optimizations, improvements to warnings and error messages
### React with Addons
- `React.addons.TestUtils` was added to help write unit tests
- `React.addons.TransitionGroup` was renamed to `React.addons.CSSTransitionGroup`
- `React.addons.TransitionGroup` was added as a more general animation wrapper
- `React.addons.cloneWithProps` was added for cloning components and modifying their props
- Bug fix for adding back nodes during an exit transition for CSSTransitionGroup
- Bug fix for changing `transitionLeave` in CSSTransitionGroup
- Performance optimizations for CSSTransitionGroup
- On checkbox `<input>` elements, `checkedLink` is now supported for two-way binding
### JSX Compiler and react-tools Package
- Whitespace normalization has changed; now space between two tags on the same line will be preserved, while newlines between two tags will be removed
- The `react-tools` npm package no longer includes the React core libraries; use the `react` package instead.
- `displayName` is now added in more cases, improving error messages and names in the React Dev Tools
- Fixed an issue where an invalid token error was thrown after a JSX closing tag
- `JSXTransformer` now uses source maps automatically in modern browsers
- `JSXTransformer` error messages now include the filename and problematic line contents when a file fails to parse

View File

@@ -1,95 +0,0 @@
---
title: "Community Round-up #17"
layout: post
author: Jonas Gebhardt
---
It's exciting to see the number of real-world React applications and components skyrocket over the past months! This community round-up features a few examples of inspiring React applications and components.
## React in the Real World
### Facebook Lookback video editor
Large parts of Facebook's web frontend are already powered by React. The recently released Facebook [Lookback video and its corresponding editor](https://www.facebook.com/lookback/edit/) are great examples of a complex, real-world React app.
### Russia's largest bank is now powered by React
Sberbank, Russia's largest bank, recently switched large parts of their site to use React, as detailed in [this post by Vyacheslav Slinko](https://groups.google.com/forum/#!topic/reactjs/Kj6WATX0atg).
### Relato
[Relato](http://bripkens.github.io/relato/) by [Ben Ripkens](https://github.com/bripkens) shows Open Source Statistics based on npm data. It features a filterable and sortable table built in React. Check it out &ndash; it's super fast!
### Makona Editor
John Lynch ([@johnrlynch](https://twitter.com/johnrlynch)) created Makona, a block-style document editor for the web. Blocks of different content types comprise documents, authored using plain markup. At the switch of a toggle, block contents are then rendered on the page. While not quite a WYSIWYG editor, Makona uses plain textareas for input. This makes it compatible with a wider range of platforms than traditional rich text editors.
<figure>[![](/react/img/blog/makona-editor.png)](http://johnthethird.github.io/makona-editor/)</figure>
### Create Chrome extensions using React
React is in no way limited to just web pages. Brandon Tilley ([@BinaryMuse](https://twitter.com/BinaryMuse)) just released a detailed walk-through of [how he built his Chrome extension "Fast Tab Switcher" using React](http://brandontilley.com/2014/02/24/creating-chrome-extensions-with-react.html).
### Twitter Streaming Client
Javier Aguirre ([@javaguirre](https://twitter.com/javaguirre)) put together a simple [twitter streaming client using node, socket.io and React](http://javaguirre.net/2014/02/11/twitter-streaming-api-with-node-socket-io-and-reactjs/).
### Sproutsheet
[Sproutsheet](http://sproutsheet.com/) is a gardening calendar. You can use it to track certain events that happen in the life of your plants. It's currently in beta and supports localStorage, and data/image import and export.
### Instant Domain Search
[Instant Domain Search](https://instantdomainsearch.com/) also uses React. It sure is instant!
### SVG-based graphical node editor
[NoFlo](http://noflojs.org/) and [Meemoo](http://meemoo.org/) developer [Forresto Oliphant](http://www.forresto.com/) built an awesome SVG-based [node editor](http://forresto.github.io/prototyping/react/) in React.
<figure>[![](/react/img/blog/react-svg-fbp.png)](http://forresto.github.io/prototyping/react/)</figure>
### Ultimate Tic-Tac-Toe Game in React
Rafał Cieślak ([@Ravicious](https://twitter.com/Ravicious)) wrote a [React version](http://ravicious.github.io/ultimate-ttt/) of [Ultimate Tic Tac Toe](http://mathwithbaddrawings.com/2013/06/16/ultimate-tic-tac-toe/). Find the source [here](https://github.com/ravicious/ultimate-ttt).
### ReactJS Gallery
[Emanuele Rampichini](https://github.com/lele85)'s [ReactJS Gallery](https://github.com/lele85/ReactGallery) is a cool demo app that shows fullscreen images from a folder on the server. If the folder content changes, the gallery app updates via websockets.
Emanuele shared this awesome demo video with us:
<iframe width="560" height="315" src="//www.youtube.com/embed/jYcpaemt90M" frameborder="0" allowfullscreen></iframe>
## React Components
### Table Sorter
[Table Sorter](http://bgerm.github.io/react-table-sorter-demo/) by [bgerm](https://github.com/bgerm) [[source](https://github.com/bgerm/react-table-sorter-demo)] is another helpful React component.
### Static-search
Dmitry Chestnykh [@dchest](https://twitter.com/dchest) wrote a [static search indexer](https://github.com/dchest/static-search) in Go, along with a [React-based web front-end](http://www.codingrobots.com/search/) that consumes search result via JSON.
### Lorem Ipsum component
[Martin Andert](https://github.com/martinandert) created [react-lorem-component](https://github.com/martinandert/react-lorem-component), a simple component for all your placeholding needs.
### Input with placeholder shim
[react-input=placeholder](https://github.com/enigma-io/react-input-placeholder) by [enigma-io](https://github.com/enigma-io) is a small wrapper around React.DOM.input that shims in placeholder functionality for browsers that don't natively support it.
### diContainer
[dicontainer](https://github.com/SpektrumFM/dicontainer) provides a dependency container that lets you inject Angular-style providers and services as simple React.js Mixins.
## React server rendering
Ever wonder how to pre-render React components on the server? [react-server-example](https://github.com/mhart/react-server-example) by Michael Hart ([@hichaelmart](http://twitter.com/hichaelmart)) walks through the necessary steps.
Similarly, Alan deLevie ([@adelevie](https://twitter.com/adelevie)) created [react-client-server-starter](https://github.com/adelevie/react-client-server-starter), another detailed walk-through of how to server-render your app.
## Random Tweet
<div><blockquote class="twitter-tweet" lang="en"><p>Recent changes: web ui is being upgraded to [#reactjs](https://twitter.com/search?q=%23reactjs&src=hash), HEAD~4 at [https://camlistore.googlesource.com/camlistore/](https://camlistore.googlesource.com/camlistore/)</p>&mdash; Camlistore (@Camlistore) <a href="https://twitter.com/Camlistore/status/423925795820539904">January 16, 2014</a></blockquote></div>

View File

@@ -1,106 +0,0 @@
---
title: "Community Round-up #18"
layout: post
author: Jonas Gebhardt
---
In this Round-up, we are taking a few closer looks at React's interplay with different frameworks and architectures.
## "Little framework BIG splash"
Let's start with yet another refreshing introduction to React: Craig Savolainen ([@maedhr](https://twitter.com/maedhr)) walks through some first steps, demonstrating [how to build a Google Maps component](http://infinitemonkeys.influitive.com/little-framework-big-splash) using React.
## Architecting your app with react
Brandon Konkle ([@bkonkle](https://twitter.com/bkonkle))
[Architecting your app with react](http://lincolnloop.com/blog/architecting-your-app-react-part-1/)
We're looking forward to part 2!
> React is not a full MVC framework, and this is actually one of its strengths. Many who adopt React choose to do so alongside their favorite MVC framework, like Backbone. React has no opinions about routing or syncing data, so you can easily use your favorite tools to handle those aspects of your frontend application. You'll often see React used to manage specific parts of an application's UI and not others. React really shines, however, when you fully embrace its strategies and make it the core of your application's interface.
>
> [Read the full article...](http://lincolnloop.com/blog/architecting-your-app-react-part-1/)
## React vs. async DOM manipulation
Eliseu Monar ([@eliseumds](https://twitter.com/eliseumds))'s post "[ReactJS vs async concurrent rendering](http://eliseu.tk/post/77843550010/vitalbox-pchr-reactjs-vs-async-concurrent-rendering)" is a great example of how React quite literally renders a whole array of common web development work(arounds) obsolete.
## React, Scala and the Play Framework
[Matthias Nehlsen](http://matthiasnehlsen.com/) wrote a detailed introductory piece on [React and the Play Framework](http://matthiasnehlsen.com/blog/2014/01/05/play-framework-and-facebooks-react-library/), including a helpful architectural diagram of a typical React app.
Nehlsen's React frontend is the second implementation of his chat application's frontend, following an AngularJS version. Both implementations are functionally equivalent and offer some perspective on differences between the two frameworks.
In [another article](http://matthiasnehlsen.com/blog/2014/01/24/scala-dot-js-and-reactjs/), he walks us through the process of using React with scala.js to implement app-wide undo functionality.
Also check out his [talk](http://m.ustream.tv/recorded/42780242) at Ping Conference 2014, in which he walks through a lot of the previously content in great detail.
## React and Backbone
The folks over at [Venmo](https://venmo.com/) are using React in conjunction with Backbone.
Thomas Boyt ([@thomasaboyt](https://twitter.com/thomasaboyt)) wrote [this detailed piece](http://www.thomasboyt.com/2013/12/17/using-reactjs-as-a-backbone-view.html) about why React and Backbone are "a fantastic pairing".
## React vs. Ember
Eric Berry ([@coderberry](https://twitter.com/coderberry)) developed Ember equivalents for some of the official React examples. Read his post for a side-by-side comparison of the respective implementations: ["Facebook React vs. Ember"](http://instructure.github.io/blog/2013/12/17/facebook-react-vs-ember/).
## React and plain old HTML
Daniel Lo Nigro ([@Daniel15](https://twitter.com/Daniel15)) created [React-Magic](https://github.com/reactjs/react-magic), which leverages React to ajaxify plain old html pages and even [allows CSS transitions between pageloads](http://stuff.dan.cx/facebook/react-hacks/magic/red.php).
> React-Magic intercepts all navigation (link clicks and form posts) and loads the requested page via an AJAX request. React is then used to "diff" the old HTML with the new HTML, and only update the parts of the DOM that have been changed.
>
> [Check out the project on GitHub...](https://github.com/reactjs/react-magic)
On a related note, [Reactize](https://turbo-react.herokuapp.com/) by Ross Allen ([@ssorallen](https://twitter.com/ssorallen)) is a similarly awesome project: A wrapper for Rails' [Turbolinks](https://github.com/rails/turbolinks/), which seems to have inspired John Lynch ([@johnrlynch](https://twitter.com/johnrlynch)) to then create [a server-rendered version using the JSX transformer in Rails middleware](http://www.rigelgroupllc.com/blog/2014/01/12/react-jsx-transformer-in-rails-middleware/).
## React and Object.observe
Check out [François de Campredon](https://github.com/fdecampredon)'s implementation of [TodoMVC based on React and ES6's Object.observe](https://github.com/fdecampredon/react-observe-todomvc/).
## React and Angular
Ian Bicking ([@ianbicking](https://twitter.com/ianbicking)) of Mozilla Labs [explains why he "decided to go with React instead of Angular.js"](https://plus.google.com/+IanBicking/posts/Qj8R5SWAsfE).
### ng-React Update
[David Chang](https://github.com/davidchang) works through some performance improvements of his [ngReact](https://github.com/davidchang/ngReact) project. His post ["ng-React Update - React 0.9 and Angular Track By"](http://davidandsuzi.com/ngreact-update/) includes some helpful advice on boosting render performance for Angular components.
> Angular gives you a ton of functionality out of the box - a full MV* framework - and I am a big fan, but I'll admit that you need to know how to twist the right knobs to get performance.
>
> That said, React gives you a very strong view component out of the box with the performance baked right in. Try as I did, I couldn't actually get it any faster. So pretty impressive stuff.
>
>[Read the full post...](http://davidandsuzi.com/ngreact-update/)
React was also recently mentioned at ng-conf, where the Angular team commented on React's concept of the virtual DOM:
<iframe width="560" height="315" src="//www.youtube.com/embed/srt3OBP2kGc?start=113" frameborder="0" allowfullscreen></iframe>
## React and Web Components
Jonathan Krause ([@jonykrause](https://twitter.com/jonykrause)) offers his thoughts regarding [parallels between React and Web Components](http://jonykrau.se/posts/the-value-of-react), highlighting the value of React's ability to render pages on the server practically for free.
## Immutable React
[Peter Hausel](http://pk11.kinja.com/) shows how to build a Wikipedia auto-complete demo based on immutable data structures (similar to [mori](https://npmjs.org/package/mori)), really taking advantage of the framework's one-way reactive data binding:
> Its truly reactive design makes DOM updates finally sane and when combined with persistent data structures one can experience JavaScript development like it was never done before.
> [Read the full post](http://tech.kinja.com/immutable-react-1495205675)
## D3 and React
[Ben Smith](http://10consulting.com/) built some great SVG-based charting components using a little less of D3 and a little more of React: [D3 and React - the future of charting components?](http://10consulting.com/2014/02/19/d3-plus-reactjs-for-charting/)
## Om and React
Josh Haberman ([@joshhaberman](https://twitter.com/JoshHaberman)) discusses performance differences between React, Om and traditional MVC frameworks in "[A closer look at OM vs React performance](http://blog.reverberate.org/2014/02/on-future-of-javascript-mvc-frameworks.html)".
Speaking of Om: [Omchaya](https://github.com/sgrove/omchaya) by Sean Grove ([@sgrove](https://twitter.com/sgrove)) is a neat Cljs/Om example project.
## Random Tweets
<div><blockquote class="twitter-tweet" lang="en"><p>Worked for 2 hours on a [@react_js](https://twitter.com/react_js) app sans internet. Love that I could get stuff done with it without googling every question.</p>&mdash; John Shimek (@varikin) <a href="https://twitter.com/varikin/status/436606891657949185">February 20, 2014</a></blockquote></div>

View File

@@ -1,71 +0,0 @@
---
title: React v0.10 RC
layout: post
author: Paul OShannessy
---
[v0.9 has only been out for a month](http://facebook.github.io/react/blog/2014/02/20/react-v0.9.html), but were getting ready to push out v0.10 already. Unlike v0.9 which took a long time, we don't have a long list of changes to talk about.
The release candidate is available for download from the CDN:
* **React**
Dev build with warnings: <http://fb.me/react-0.10.0-rc1.js>
Minified build for production: <http://fb.me/react-0.10.0-rc1.min.js>
* **React with Add-Ons**
Dev build with warnings: <http://fb.me/react-with-addons-0.10.0-rc1.js>
Minified build for production: <http://fb.me/react-with-addons-0.10.0-rc1.min.js>
* **In-Browser JSX transformer**
<http://fb.me/JSXTransformer-0.10.0-rc1.js>
We've also published version `0.10.0-rc1` of the `react` and `react-tools` packages on npm and the `react` package on bower.
Please try these builds out and [file an issue on GitHub](https://github.com/facebook/react/issues/new) if you see anything awry.
## Clone On Mount
The main purpose of this release is to provide a smooth upgrade path as we evolve some of the implementation of core. In v0.9 we started warning in cases where you called methods on unmounted components. This is part of an effort to enforce the idea that the return value of a component (`React.DOM.div()`, `MyComponent()`) is in fact not a reference to the component instance React uses in the virtual DOM. The return value is instead a light-weight object that React knows how to use. Since the return value currently is a reference to the same object React uses internally, we need to make this transition in stages as many people have come to depend on this implementation detail.
In 0.10, were adding more warnings to catch a similar set of patterns. When a component is mounted we clone it and use that object for our internal representation. This allows us to capture calls you think youre making to a mounted component. Well forward them on to the right object, but also warn you that this is breaking. See “Access to the Mounted Instance” on [this page](http://fb.me/react-warning-descriptors). Most of the time you can solve your pattern by using refs.
Storing a reference to your top level component is a pattern touched upon on that page, but another examples that demonstrates what we see a lot of:
```js
// This is a common pattern. However instance here really refers to a
// "descriptor", not necessarily the mounted instance.
var instance = <MyComponent/>;
React.renderComponent(instance);
// ...
instance.setProps(...);
// The change here is very simple. The return value of renderComponent will be
// the mounted instance.
var instance = React.renderComponent(<MyComponent/>)
// ...
instance.setProps(...);
```
These warnings and method forwarding are only enabled in the development build. The production builds continue to work as they did in v0.9. We strongly encourage you to use the development builds to catch these warnings and fix the call sites.
The plan for v0.11 is that we will go fully to "descriptors". Method calls on the return value of `MyComponent()` will fail hard.
## Changelog
### React Core
#### New Features
* Made it possible to server render without React-related markup (`data-reactid`, `data-react-checksum`) - `React.renderComponentToStaticMarkup`
* Added support for more attributes:
* `srcSet` for `<img>` to images at different pixel ratios
* `textAnchor` for SVG
#### Bug Fixes
* Ensure all void elements dont insert a closing tag into the markup.
* Ensure `className={false}` behaves consistently
* Ensure `this.refs` is defined, even if no refs are specified.
### Addons
* `update` function to deal with immutable data.
### react-tools
* Added an option argument to `transform` function. The only option supported is `harmony`, which behaves the same as `jsx --harmony` on the command line. This uses the ES6 transforms from [jstransform](https://github.com/facebook/jstransform).

View File

@@ -1,127 +0,0 @@
---
id: acknowledgements
title: Acknowledgements
layout: single
---
We'd like to thank all of our contributors:
<div class="three-column">
<ul>
<li>Alan deLevie</li>
<li>Alex Zelenskiy</li>
<li>Alexander Solovyov</li>
<li>Andreas Svensson</li>
<li>Andrew Davey</li>
<li>Andrew Zich</li>
<li>Andrey Popp</li>
<li>Ayman Osman</li>
<li>Ben Alpert</li>
<li>Ben Newman</li>
<li>Ben Ripkens</li>
<li>Bob Eagan</li>
<li>Brian Cooke</li>
<li>Brian Kim</li>
<li>Brian Rue</li>
<li>Cam Spiers</li>
<li>Cat Chen</li>
<li>Cheng Lou</li>
<li>Christian Roman</li>
<li>Christoph Pojer</li>
<li>Clay Allsopp</li>
<li>Connor McSheffrey</li>
<li>Dan Schafer</li>
<li>Daniel Gasienica</li>
<li>Daniel Lo Nigro</li>
<li>Daniel Miladinov</li>
<li>Danny Ben-David</li>
<li>David Hellsing</li>
<li>David Hu</li>
<li>Dustin Getz</li>
<li>Eric Clemmons</li>
<li>Eric Schoffstall</li>
<li>Fabio M. Costa</li>
<li>Felipe Oliveira Carvalho</li>
<li>Felix Kling</li>
<li>Fernando Correia</li>
<li>Greg Roodt</li>
</ul>
<ul>
<li>Guido Bouman</li>
<li>Harry Hull</li>
<li>Hugo Jobling</li>
<li>Ian Obermiller</li>
<li>Ingvar Stepanyan</li>
<li>Isaac Salier-Hellendag</li>
<li>Ivan Kozik</li>
<li>Jakub Malinowski</li>
<li>James Ide</li>
<li>Jamie Wong</li>
<li>Jamison Dance</li>
<li>Jan Kassens</li>
<li>Jared Forsyth</li>
<li>Jason Bonta</li>
<li>Jason Trill</li>
<li>Jean Lauliac</li>
<li>Jeff Morrison</li>
<li>Jeffrey Lin</li>
<li>Jignesh Kakadiya</li>
<li>Johannes Baiter</li>
<li>John Watson</li>
<li>Jonas Gebhardt</li>
<li>Jonathan Hsu</li>
<li>Jordan Walke</li>
<li>Josh Duck</li>
<li>Jun Wu</li>
<li>Keito Uchiyama</li>
<li>Kit Randel</li>
<li>Kunal Mehta</li>
<li>Laurence Rowe</li>
<li>Levi McCallum</li>
<li>Logan Allen</li>
<li>Luigy Leon</li>
<li>Mark Richardson</li>
<li>Marshall Roch</li>
<li>Martin Andert</li>
<li>Martin Konicek</li>
</ul>
<ul>
<li>Mathieu M-Gosselin</li>
<li>Matt Harrison</li>
<li>Matti Nelimarkka</li>
<li>Michal Srb</li>
<li>Mouad Debbar</li>
<li>Nadeesha Cabral</li>
<li>Nicholas Bergson-Shilcock</li>
<li>Nick Gavalas</li>
<li>Nick Thompson</li>
<li>Owen Coutts</li>
<li>Pascal Hartig</li>
<li>Paul OShannessy</li>
<li>Paul Seiffert</li>
<li>Paul Shen</li>
<li>Pete Hunt</li>
<li>Peter Cottle</li>
<li>Petri Lievonen</li>
<li>Pieter Vanderwerff</li>
<li>Richard D. Worth</li>
<li>Richard Feldman</li>
<li>Richard Livesey</li>
<li>Sander Spies</li>
<li>Sean Kinsey</li>
<li>Sebastian Markbåge</li>
<li>Shaun Trennery</li>
<li>Simon Højberg</li>
<li>Stoyan Stefanov</li>
<li>Sundeep Malladi</li>
<li>Thomas Aylott</li>
<li>Timothy Yung</li>
<li>Tom Occhino</li>
<li>Vjeux</li>
<li>Wincent Colaiuta</li>
<li>Zach Bruggeman</li>
<li>imagentleman</li>
</ul>
</div>
In addition, we're grateful to [Jeff Barczewski](https://github.com/jeffbski) for allowing us to use the `react` package name on npm.

View File

@@ -13,6 +13,17 @@ JSX looks like HTML but there are some important differences you may run into.
>
> For DOM differences, such as the inline `style` attribute, check [here](/react/docs/dom-differences.html).
## Whitespace Removal
JSX doesn't follow the same whitespace elimination rules as HTML. JSX removes all whitespace between two curly braces expressions. If you want to have whitespace, simply add `{' '}`.
```javascript
<div>{this.props.name} {' '} {this.props.surname}</div>
```
Follow [Issue #65](https://github.com/facebook/react/issues/65) for discussion on this behavior.
## HTML Entities
You can insert HTML entities within literal text in JSX:

View File

@@ -73,7 +73,7 @@ When you create a React component instance, you can include additional React com
<Parent><Child /></Parent>
```
`Parent` can read its children by accessing the special `this.props.children` prop. **`this.props.children` is an opaque data structure:** use the [React.Children utilities](/react/docs/top-level-api.html#react.children) to manipulate them.
`Parent` can read its children by accessing the special `this.props.children` prop.
### Child Reconciliation
@@ -124,7 +124,7 @@ The situation gets more complicated when the children are shuffled around (as in
var results = this.props.results;
return (
<ol>
{results.map(function(result) {
{this.results.map(function(result) {
return <li key={result.id}>{result.text}</li>;
})}
</ol>
@@ -134,26 +134,6 @@ The situation gets more complicated when the children are shuffled around (as in
When React reconciles the keyed children, it will ensure that any child with `key` will be reordered (instead of clobbered) or destroyed (instead of reused).
You can also key children by passing an object. The object keys will be used as `key` for each value. However it is important to remember that JavaScript does not guarantee the ordering of properties will be preserved. In practice browsers will preserve property order **except** for properties that can be parsed as a 32-bit unsigned integers. Numeric properties will be ordered sequentially and before other properties. If this happens React will render components out of order. This can be avoided by adding a string prefix to the key:
```javascript
render: function() {
var items = {};
this.props.results.forEach(function(result) {
// If result.id can look like a number (consider short hashes), then
// object iteration order is not guaranteed. In this case, we add a prefix
// to ensure the keys are strings.
items['result-' + result.id] = <li>{result.text}</li>;
});
return (
<ol>
{items}
</ol>
);
}
```
## Data Flow

View File

@@ -12,7 +12,7 @@ When designing interfaces, break down the common design elements (buttons, form
## Prop Validation
As your app grows it's helpful to ensure that your components are used correctly. We do this by allowing you to specify `propTypes`. `React.PropTypes` exports a range of validators that can be used to make sure the data you receive is valid. When an invalid value is provided for a prop, a warning will be shown in the JavaScript console. Note that for performance reasons `propTypes` is only checked in development mode. Here is an example documenting the different validators provided:
As your app grows it's helpful to ensure that your components are used correctly. We do this by allowing you to specify `propTypes`. `React.PropTypes` exports a range of validators that can be used to make sure the data you receive is valid. When an invalid value is provided for a prop, an error will be thrown. Here is an example documenting the different validators provided:
```javascript
React.createClass({
@@ -26,48 +26,22 @@ React.createClass({
optionalObject: React.PropTypes.object,
optionalString: React.PropTypes.string,
// Anything that can be rendered: numbers, strings, components or an array
// containing these types.
optionalRenderable: React.PropTypes.renderable,
// A React component.
optionalComponent: React.PropTypes.component,
// You can ensure that your prop is limited to specific values by treating
// it as an enum.
optionalEnum: React.PropTypes.oneOf(['News','Photos']),
// You can also declare that a prop is an instance of a class. This uses
// JS's instanceof operator.
optionalMessage: React.PropTypes.instanceOf(Message),
someClass: React.PropTypes.instanceOf(SomeClass),
// You can ensure that your prop is limited to specific values by treating
// it as an enum.
optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
// An object that could be one of many types
optionalUnion: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number,
React.PropTypes.instanceOf(Message)
]),
// An array of a certain type
optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
// An object taking on a particular shape
optionalObjectWithShape: React.PropTypes.shape({
color: React.PropTypes.string,
fontSize: React.PropTypes.number
}),
// You can chain any of the above with isRequired to make sure a warning is
// shown if the prop isn't provided.
requiredFunc: React.PropTypes.func.isRequired,
// An object of any kind
requiredAny: React.PropTypes.any.isRequired,
// You can chain any of the above with isRequired to make sure an error is
// thrown if the prop isn't provided.
requiredFunc: React.PropTypes.func.isRequired
// You can also specify a custom validator.
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
console.warn('Validation failed!');
throw new Error('Validation failed!')
}
}
},
@@ -117,26 +91,6 @@ React.renderComponent(
);
```
## Single Child
With `React.PropTypes.component` you can specify that only a single child can be passed to
a component as children.
```javascript
var MyComponent = React.createClass({
propTypes: {
children: React.PropTypes.component.isRequired
},
render: function() {
return
<div>
{this.props.children} // This must be exactly one element or it will throw.
</div>;
}
});
```
## Mixins

View File

@@ -80,7 +80,7 @@ React provides lifecycle methods that you can specify to hook into this process.
* `getInitialState(): object` is invoked before a component is mounted. Stateful components should implement this and return the initial state data.
* `componentWillMount()` is invoked immediately before mounting occurs.
* `componentDidMount()` is invoked immediately after mounting occurs. Initialization that requires DOM nodes should go here.
* `componentDidMount(DOMElement rootNode)` is invoked immediately after mounting occurs. Initialization that requires DOM nodes should go here.
### Updating
@@ -88,7 +88,7 @@ React provides lifecycle methods that you can specify to hook into this process.
* `componentWillReceiveProps(object nextProps)` is invoked when a mounted component receives new props. This method should be used to compare `this.props` and `nextProps` to perform state transitions using `this.setState()`.
* `shouldComponentUpdate(object nextProps, object nextState): boolean` is invoked when a component decides whether any changes warrant an update to the DOM. Implement this as an optimization to compare `this.props` with `nextProps` and `this.state` with `nextState` and return false if React should skip updating.
* `componentWillUpdate(object nextProps, object nextState)` is invoked immediately before updating occurs. You cannot call `this.setState()` here.
* `componentDidUpdate(object prevProps, object prevState)` is invoked immediately after updating occurs.
* `componentDidUpdate(object prevProps, object prevState, DOMElement rootNode)` is invoked immediately after updating occurs.
### Unmounting
@@ -103,6 +103,12 @@ _Mounted_ composite components also support the following methods:
* `getDOMNode(): DOMElement` can be invoked on any mounted component in order to obtain a reference to its rendered DOM node.
* `forceUpdate()` can be invoked on any mounted component when you know that some deeper aspect of the component's state has changed without using `this.setState()`.
> Note:
>
> The `DOMElement rootNode` argument of `componentDidMount()` and
> `componentDidUpdate()` is a convenience. The same node can be obtained by
> calling `this.getDOMNode()`.
## Browser Support and Polyfills
@@ -121,23 +127,19 @@ In addition to that philosophy, we've also taken the stance that we, as authors
* `Array.prototype.some`
* `Date.now`
* `Function.prototype.bind`
* `Object.keys`
`es5-sham.js`, also from [kriskowal's es5-shim](https://github.com/kriskowal/es5-shim), provides the following that React needs:
* `Object.create`
* `Object.freeze`
The unminified build of React needs the following from [paulmillr's console-polyfill](https://github.com/paulmillr/console-polyfill).
* `console.*`
When using HTML5 elements in IE8 including `<section>`, `<article>`, `<nav>`, `<header>`, and `<footer>`, it's also necessary to include [html5shiv](https://github.com/aFarkas/html5shiv) or a similar script.
### Cross-browser Issues
Although React is pretty good at abstracting browser differences, some browsers are limited or present quirky behaviors that we couldn't find a workaround for.
Although React is pretty good at abstracting browser differences, some browsers are limited or present quirky behaviors that we couldn't find a workaround.
#### onScroll event on IE8

View File

@@ -38,7 +38,14 @@ If you have [npm](http://npmjs.org/), you can simply run `npm install -g react-t
### Helpful Open-Source Projects
The open-source community has built tools that integrate JSX with several build systems. See [JSX integrations](/react/docs/complementary-tools.html#jsx-integrations) for the full list.
The open-source community has built tools that integrate JSX with several build systems.
* [reactify](https://github.com/andreypopp/reactify) - use JSX with [browserify](http://browserify.org/)
* [grunt-react](https://github.com/ericclemmons/grunt-react) - [grunt](http://gruntjs.com/) task for JSX
* [gulp-react](https://github.com/sindresorhus/gulp-react) - [gulp](http://gulpjs.com/) task for JSX
* [jsx-requirejs-plugin](https://github.com/philix/jsx-requirejs-plugin) - use JSX with [require.js](http://requirejs.org/) and precompile JSX files with r.js
* [pyReact](https://github.com/facebook/react-python) - use JSX with [Python](http://www.python.org/)
* [react-rails](https://github.com/facebook/react-rails) - use JSX with [Ruby on Rails](http://rubyonrails.org/)
### Syntax Highlighting & Linting
@@ -46,10 +53,5 @@ The open-source community has built tools that integrate JSX with several build
* Many editors already include reasonable support for JSX (Vim, Emacs js2-mode).
* [JSX syntax highlighting](https://github.com/yungsters/sublime/blob/master/tmLanguage/JavaScript%20(JSX\).tmLanguage) is available for Sublime Text and other editors
that support `*.tmLanguage`.
* [web-mode.el](http://web-mode.org) is an autonomous emacs major mode that indents and highlights JSX
* Linting provides accurate line numbers after compiling without sourcemaps.
* Elements use standard scoping so linters can find usage of out-of-scope components.
### Debugging
[React Developer Tools](https://github.com/facebook/react-devtools) is a [Chrome extension](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en) that allows you to inspect the React component hierarchy in the Chrome Developer Tools.

View File

@@ -9,11 +9,8 @@ next: animation.html
`React.addons` is where we park some useful utilities for building React apps. **These should be considered experimental** but will eventually be rolled into core or a blessed utilities library:
- [`ReactTransitions`](animation.html), for dealing with animations and transitions that are usually not simple to implement, such as before a component's removal.
- [`ReactLink`](two-way-binding-helpers.html), to simplify the coordination between user's form input data and and the component's state.
- [`classSet()`](class-name-manipulation.html), for manipulating the DOM `class` string a bit more cleanly.
- [`ReactTestUtils`](test-utils.html), simple helpers for writing test cases (unminified build only).
- [`cloneWithProps()`](clone-with-props.html), to make shallow copies of React components and change their props.
- [`update()`](update.html), a helper function that makes dealing with immutable data in JavaScript easier.
- `ReactTransitions`, for dealing with animations and transitions that are usually not simple to implement, such as before a component's removal.
- `ReactLink`, to simplify the coordination between user's form input data and and the component's state.
- `classSet`, for manipulating the DOM `class` string a bit more cleanly.
To get the add-ons, use `react-with-addons.js` (and its minified counterpart) rather than the common `react.js`.

View File

@@ -7,20 +7,16 @@ prev: addons.html
next: two-way-binding-helpers.html
---
React provides a `ReactTransitionGroup` addon component as a low-level API for animation, and a `ReactCSSTransitionGroup` for easily implementing basic CSS animations and transitions.
`ReactTransitions` is an easy way to perform CSS transitions and animations when a React component enters or leaves the DOM. It's inspired by the excellent [ng-animate](http://www.nganimate.org/) library.
## High-level API: `ReactCSSTransitionGroup`
## Getting Started
`ReactCSSTransitionGroup` is based on `ReactTransitionGroup` and is an easy way to perform CSS transitions and animations when a React component enters or leaves the DOM. It's inspired by the excellent [ng-animate](http://www.nganimate.org/) library.
### Getting Started
`ReactCSSTransitionGroup` is the interface to `ReactTransitions`. This is a simple element that wraps all of the components you are interested in animating. Here's an example where we fade list items in and out.
`ReactTransitionGroup` is the interface to `ReactTransitions`. This is a simple element that wraps all of the components you are interested in animating. Here's an example where we fade list items in and out.
```javascript{22-24}
/** @jsx React.DOM */
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
var ReactTransitionGroup = React.addons.TransitionGroup;
var TodoList = React.createClass({
getInitialState: function() {
@@ -47,16 +43,16 @@ var TodoList = React.createClass({
return (
<div>
<div><button onClick={this.handleAdd} /></div>
<ReactCSSTransitionGroup transitionName="example">
<ReactTransitionGroup transitionName="example">
{items}
</ReactCSSTransitionGroup>
</ReactTransitionGroup>
</div>
);
}
});
```
In this component, when a new item is added to `ReactCSSTransitionGroup` it will get the `example-enter` CSS class and the `example-enter-active` CSS class added in the next tick. This is a convention based on the `transitionName` prop.
In this component, when a new item is added to `ReactTransitionGroup` it will get the `example-enter` CSS class and the `example-enter-active` CSS class added in the next tick. This is a convention based on the `transitionName` prop.
You can use these classes to trigger a CSS animation or transition. For example, try adding this CSS and adding a new list item:
@@ -71,7 +67,7 @@ You can use these classes to trigger a CSS animation or transition. For example,
}
```
You'll notice that when you try to remove an item `ReactCSSTransitionGroup` keeps it in the DOM. If you're using an unminified build of React with add-ons you'll see a warning that React was expecting an animation or transition to occur. That's because `ReactCSSTransitionGroup` keeps your DOM elements on the page until the animation completes. Try adding this CSS:
You'll notice that when you try to remove an item `ReactTransitionGroup` keeps it in the DOM. If you're using an unminified build of React with add-ons you'll see a warning that React was expecting an animation or transition to occur. That's because `ReactTransitionGroup` keeps your DOM elements on the page until the animation completes. Try adding this CSS:
```css
.example-leave {
@@ -84,36 +80,18 @@ You'll notice that when you try to remove an item `ReactCSSTransitionGroup` keep
}
```
### Disabling Animations
## Disabling Animations
You can disable animating `enter` or `leave` animations if you want. For example, sometimes you may want an `enter` animation and no `leave` animation, but `ReactCSSTransitionGroup` waits for an animation to complete before removing your DOM node. You can add `transitionEnter={false}` or `transitionLeave={false}` props to `ReactCSSTransitionGroup` to disable these animations.
You can disable animating `enter` or `leave` animations if you want. For example, sometimes you may want an `enter` animation and no `leave` animation, but `ReactTransitionGroup` waits for an animation to complete before removing your DOM node. You can add `transitionEnter={false}` or `transitionLeave={false}` props to `ReactTransitionGroup` to disable these animations.
## Low-level API: `ReactTransitionGroup`
`ReactTransitionGroup` is the basis for animations. When children are declaratively added or removed from it (as in the example above) special lifecycle hooks are called on them.
### `componentWillEnter(callback)`
This is called at the same time as `componentDidMount()` for components added to an existing `TransitionGroup`. It will block other animations from occurring until `callback` is called. It will not be called on the initial render of a `TransitionGroup`.
### `componentDidEnter()`
This is called after the `callback` function that was passed to `componentWillEnter` is called.
### `componentWillLeave(callback)`
This is called when the child has been removed from the `ReactTransitionGroup`. Though the child has been removed, `ReactTransitionGroup` will keep it in the DOM until `callback` is called.
### `componentDidLeave()`
This is called when the `willLeave` `callback` is called (at the same time as `componentWillUnmount`).
### Rendering a Different Component
## Rendering a Different Component
By default `ReactTransitionGroup` renders as a `span`. You can change this behavior by providing a `component` prop. For example, here's how you would render a `<ul>`:
```javascript{1}
<ReactTransitionGroup component={React.DOM.ul}>
```javascript{3}
<ReactTransitionGroup
transitionName="example"
component={React.DOM.ul}>
...
</ReactTransitionGroup>
```

View File

@@ -66,8 +66,6 @@ var WithLink = React.createClass({
`ReactLink` objects can be passed up and down the tree as props, so it's easy (and explicit) to set up two-way binding between a component deep in the hierarchy and state that lives higher in the hierarchy.
Note that `<input>` supports ReactLink for both `value` and `checked`.
## Under the Hood
There are two sides to `ReactLink`: the place where you create the `ReactLink` instance and the place where you use it. To prove how simple `ReactLink` is, let's rewrite each side separately to be more explicit.

View File

@@ -4,7 +4,7 @@ title: Class Name Manipulation
layout: docs
permalink: class-name-manipulation.html
prev: two-way-binding-helpers.html
next: test-utils.html
next: examples.html
---
`classSet()` is a neat utility for easily manipulating the DOM `class` string.

View File

@@ -1,140 +0,0 @@
---
id: test-utils
title: Test Utilities
layout: docs
permalink: test-utils.html
prev: class-name-manipulation.html
next: clone-with-props.html
---
`React.addons.TestUtils` makes it easy to test React components in the testing framework of your choice (we use [Jasmine](http://pivotal.github.io/jasmine/) with [jsdom](https://github.com/tmpvar/jsdom)).
### Simulate
```javascript
Simulate.{eventName}({ReactComponent|DOMElement} element, object eventData)
```
Simulate an event dispatch on a React component instance or browser DOM node with optional `eventData` event data. **This is possibly the single most useful utility in `ReactTestUtils`.**
Example usage:
```javascript
React.addons.TestUtils.Simulate.click(myComponent);
React.addons.TestUtils.Simulate.change(myComponent);
React.addons.TestUtils.Simulate.keydown(myComponent, {key: "Enter"});
```
`Simulate` has a method for every event that React understands.
### renderIntoDocument
```javascript
ReactComponent renderIntoDocument(ReactComponent instance)
```
Render a component into a detached DOM node in the document. **This function requires a DOM.**
### mockComponent
```javascript
object mockComponent(function componentClass, string? tagName)
```
Pass a mocked component module to this method to augment it with useful methods that allow it to be used as a dummy React component. Instead of rendering as usual, the component will become a simple `<div>` (or other tag if `mockTagName` is provided) containing any provided children.
### isComponentOfType
```javascript
boolean isComponentOfType(ReactComponent instance, function componentClass)
```
Returns true if `instance` is an instance of a React `componentClass`.
### isDOMComponent
```javascript
boolean isDOMComponent(ReactComponent instance)
```
Returns true if `instance` is a DOM component (such as a `<div>` or `<span>`).
### isCompositeComponent
```javascript
boolean isCompositeComponent(ReactComponent instance)`
```
Returns true if `instance` is a composite component (created with `React.createClass()`)
### isCompositeComponentWithType
```javascript
boolean isCompositeComponentWithType(ReactComponent instance, function componentClass)
```
The combination of `isComponentOfType()` and `isCompositeComponent()`.
### isTextComponent
```javascript
boolean isTextComponent(ReactComponent instance)
```
Returns true if `instance` is a plain text component.
### findAllInRenderedTree
```javascript
array findAllInRenderedTree(ReactComponent tree, function test)
```
Traverse all components in `tree` and accumulate all components where `test(component)` is true. This is not that useful on its own, but it's used as a primitive for other test utils.
### scryRenderedDOMComponentsWithClass
```javascript
array scryRenderedDOMComponentsWithClass(ReactCompoennt tree, string className)
```
Finds all instance of components in the rendered tree that are DOM components with the class name matching `className`.
### findRenderedDOMComponentWithClass
```javascript
ReactComponent findRenderedDOMComponentWithClass(ReactComponent tree, string className)
```
Like `scryRenderedDOMComponentsWithClass()` but expects there to be one result, and returns that one result, or throws exception if there is any other number of matches besides one.
### scryRenderedDOMComponentsWithTag
```javascript
array scryRenderedDOMComponentsWithTag(ReactComponent tree, string tagName)
```
Finds all instance of components in the rendered tree that are DOM components with the tag name matching `tagName`.
### findRenderedDOMComponentWithTag
```javascript
ReactComponent findRenderedDOMComponentWithTag(ReactComponent tree, string tagName)
```
Like `scryRenderedDOMComponentsWithTag()` but expects there to be one result, and returns that one result, or throws exception if there is any other number of matches besides one.
### scryRenderedComponentsWithType
```javascript
array scryRenderedComponentsWithType(ReactComponent tree, function componentClass)
```
Finds all instances of components with type equal to `componentClass`.
### findRenderedComponentWithType
```javascript
ReactComponent findRenderedComponentWithType(ReactComponent tree, function componentClass)
```
Same as `scryRenderedComponentsWithType()` but expects there to be one result and returns that one result, or throws exception if there is any other number of matches besides one.

View File

@@ -1,14 +0,0 @@
---
id: clone-with-props
title: Cloning Components
layout: docs
permalink: clone-with-props.html
prev: test-utils.html
next: update.html
---
In rare situations a component may want to change the props of a component that it doesn't own (like changing the `className` of a component passed as `this.props.children`). Other times it may want to make multiple copies of a component passed to it. `cloneWithProps()` makes this possible.
#### `ReactComponent React.addons.cloneWithProps(ReactComponent component, object? extraProps)`
Do a shallow copy of `component` and merge any props provided by `extraProps`. Props are merged in the same manner as [`transferPropsTo()`](/react/docs/component-api.html#transferpropsto), so props like `className` will be merged intelligently.

View File

@@ -1,62 +0,0 @@
---
id: update
title: Immutability Helpers
layout: docs
permalink: update.html
prev: clone-with-props.html
---
React lets you use whatever style of data management you want, including mutation. However, if you can use immutable data in performance-critical parts of your application it's easy to implement a fast `shouldComponentUpdate()` method to significantly speed up your app.
Dealing with immutable data in JavaScript is more difficult than in languages designed for it, like [Clojure](http://clojure.org/). However, we've provided a simple immutability helper, `update()`, that makes dealing with this type of data much easier, *without* fundamentally changing how your data is represented.
## The main idea
If you mutate data like this:
```javascript
myData.x.y.z = 7;
myData.a.b.push(9);
```
you have no way of determining which data has changed since the previous copy is destroyed. Instead, you need to create a new copy of `myData` and change only the parts of it that need to be changed. Then you can compare the old copy of `myData` with the new one in `shouldComponentUpdate()` using triple-equals:
```javascript
var newData = deepCopy(myData);
newData.x.y.z = 7;
newData.a.b.push(9);
```
Unfortunately, deep copies are expensive, and sometimes impossible. You can alleviate this by only copying objects that need to be changed and by reusing the objects that haven't changed. Unfortunately, in today's JavaScript this can be cumbersome:
```javascript
var newData = extend(myData, {
x: extend(myData.x, {
y: extend(myData.x.y, {z: 7}),
}),
a: extend(myData.a, {b: myData.a.b.concat(9)})
});
```
While this is fairly performant (since it only shallow copies `log n` objects and reuses the rest), it's a big pain to write. Look at all the repetition! This is not only annoying, but also provides a large surface area for bugs.
`update()` provides simple syntactic sugar around this pattern to make writing this code easier. This code becomes:
```javascript
var newData = React.addons.update(myData, {
x: {y: {z: {$set: 7}}},
a: {b: {$push: [7]}}
});
```
While the syntax takes a little getting used to (though it's inspired by [MongoDB's query language](http://docs.mongodb.org/manual/core/crud-introduction/#query)) there's no redundancy, it's statically analyzable and it's not much more typing than the mutative version.
The `$`-prefixed keys are called *directives*. The data structure they are "mutating" is called the *target*.
## Available directives
* `{$push: array}` `push()` all the items in `array` on the target
* `{$unshift: array}` `unshift()` all the items in `array` on the target
* `{$splice: array of arrays}` for each item in `array()` call `splice()` on the target with the parameters provided by the item.
* `{$set: any}` replace the target entirely
* `{$merge: object}` merge the keys of `object` with the target

21
docs/docs/10-examples.md Normal file
View File

@@ -0,0 +1,21 @@
---
id: examples
title: Examples
layout: docs
permalink: examples.html
prev: class-name-manipulation.html
---
### Production Apps
* All of [Instagram.com](http://instagram.com/) is built on React.
* Many components on [Facebook.com](http://www.facebook.com/), including the commenting interface, ads creation flows, and page insights.
* [Khan Academy](http://khanacademy.org/) is using React for most new JS development.
### Sample Code
* We've included [a step-by-step comment box tutorial](/react/docs/tutorial.html).
* [The React starter kit](/react/downloads.html) includes several examples which you can [view online in our GitHub repository](https://github.com/facebook/react/tree/master/examples/).
* [React one-hour email](https://github.com/petehunt/react-one-hour-email/commits/master) goes step-by-step from a static HTML mock to an interactive email reader (written in just one hour!)
* [Rendr + React app template](https://github.com/petehunt/rendr-react-template/) demonstrates how to use React's server rendering capabilities.

View File

@@ -4,7 +4,7 @@ title: Complementary Tools
layout: docs
permalink: complementary-tools.html
prev: videos.html
next: examples.html
next: example-apps.html
---
React is a small library that does one thing well. Here's a list of tools we've found that work really well with React when building applications.
@@ -13,48 +13,34 @@ If you want your project on this list, or think one of these projects should be
### JSX integrations
* **[jsxhint](https://npmjs.org/package/jsxhint)** [JSHint](http://jshint.com/) (linting) support.
* **[reactify](https://npmjs.org/package/reactify)** [Browserify](http://browserify.org/) transform.
* **[node-jsx](https://npmjs.org/package/node-jsx)** Native [Node](http://nodejs.org/) support.
* **[jsx-loader](https://npmjs.org/package/jsx-loader)** Loader for [webpack](http://webpack.github.io/).
* **[grunt-react](https://npmjs.org/package/grunt-react)** [GruntJS](http://gruntjs.com/) task.
* **[gulp-react](https://npmjs.org/package/gulp-react)** [GulpJS](http://gulpjs.com/) plugin.
* **[jsx-requirejs-plugin](https://github.com/philix/jsx-requirejs-plugin)** [RequireJS](http://requirejs.org/) plugin.
* **[react-meteor](https://github.com/benjamn/react-meteor)** [Meteor](http://www.meteor.com/) plugin.
* **[pyReact](https://github.com/facebook/react-python)** [Python](http://www.python.org/) bridge to JSX.
* **[react-rails](https://github.com/facebook/react-rails)** Ruby gem for using JSX with [Ruby on Rails](http://rubyonrails.org/).
* **[jsxhint](https://npmjs.org/package/jsxhint)** [JSHint](http://jshint.com/) (linting) support
* **[reactify](https://npmjs.org/package/reactify)** [Browserify](http://browserify.org/) transform
* **[node-jsx](https://npmjs.org/package/node-jsx)** Native [Node](http://nodejs.org/) support
* **[jsx-loader](https://npmjs.org/package/jsx-loader)** Loader for [webpack](http://webpack.github.io/)
* **[grunt-react](https://npmjs.org/package/grunt-react)** [GruntJS](http://gruntjs.com/) task
* **[gulp-react](https://npmjs.org/package/gulp-react)** [GulpJS](http://gulpjs.com/) plugin
* **[jsx-requirejs-plugin](https://github.com/philix/jsx-requirejs-plugin)** [RequireJS](http://requirejs.org/) plugin
### Full-stack starter kits
* **[react-quickstart](https://github.com/andreypopp/react-quickstart)** Quick-start template for `express`, `browserify`, `react-router-component` and `react-async` (**includes "isomorphic" server rendering**).
* **[generator-react-webpack](https://github.com/newtriks/generator-react-webpack)** [Yeoman](http://yeoman.io/) generator for React and Webpack.
* **[Genesis Skeleton](http://genesis-skeleton.com/)** Modern, opinionated, full-stack starter kit for rapid, streamlined application development (supports React).
* **[react-starter-template](https://github.com/johnthethird/react-starter-template)** Starter template with Gulp, Webpack and Bootstrap.
* **[react-brunch](https://npmjs.org/package/react-brunch)** [Brunch](http://brunch.io/) plugin.
* **[react-browserify-template](https://github.com/petehunt/react-browserify-template)** Quick-start with Browserify.
* **[react-app](https://github.com/andreypopp/react-app)** Rapid appliaction development with React with server rendering
* **[generator-react-webpack](https://github.com/newtriks/generator-react-webpack)** [Yeoman](http://yeoman.io/) generator for React and Webpack
* **[Genesis Skeleton](http://genesis-skeleton.com/)** Modern, opinionated, full-stack starter kit for rapid, streamlined application development (supports React)
* **[react-starter-template](https://github.com/johnthethird/react-starter-template)** Starter template with Gulp, Webpack and Bootstrap
* **[react-brunch](https://npmjs.org/package/react-brunch)** [Brunch](http://brunch.io/) plugin
* **[react-browserify-template](https://github.com/petehunt/react-browserify-template)** Quick-start with Browserify
### Routing
* **[director](https://github.com/flatiron/director)** (For an example see [TodoMVC](https://github.com/tastejs/todomvc/blob/gh-pages/architecture-examples/react/js/app.jsx#L29)).
* **[Backbone](http://backbonejs.org/)** (For an example see [github-issues-viewer](https://github.com/jaredly/github-issues-viewer)).
* **[react-router](https://github.com/jaredly/react-router)** (Example coming soon).
* **[react-router-component](http://andreypopp.viewdocs.io/react-router-component)**
* **[director](https://github.com/flatiron/director)** (for an example see [TodoMVC](https://github.com/tastejs/todomvc/blob/gh-pages/architecture-examples/react/js/app.jsx#L29))
* **[Backbone](https://backbonejs.org/)** (for an example see [github-issues-viewer](https://github.com/jaredly/github-issues-viewer))
### Model management
* **[react.backbone](https://github.com/usepropeller/react.backbone)** Use [Backbone](http://backbonejs.org) models with React.
* **[cortex](https://github.com/mquan/cortex/)** A JavaScript library for centrally managing data with React.
* **[avers](https://github.com/wereHamster/avers)** A modern client-side model abstraction library.
### Data fetching
* **[react-async](http://andreypopp.viewdocs.io/react-async)** Adds a `getInitialStateAsync(cb)` method suitable for data fetching on both the client and the server.
* **[superagent](http://visionmedia.github.io/superagent/)** A lightweight "isomorphic" library for AJAX requests.
* **[react.backbone](https://github.com/usepropeller/react.backbone)** Use [Backbone](http://backbonejs.org) models with React
* **[cortex](https://github.com/mquan/cortex/)** A JavaScript library for centrally managing data with React
### UI components
* **[react-bootstrap](https://github.com/stevoland/react-bootstrap)** Bootstrap 3 components built with React.
* **[react-topcoat](https://github.com/plaxdan/react-topcoat)** Topcoat components built with React.
* **[react-lorem-component](https://github.com/martinandert/react-lorem-component)** Lorem Ipsum placeholder component.
* **[wingspan-forms](https://github.com/wingspan/wingspan-forms)** React library for dynamic forms & grids; widgets provided by KendoUI.
* **[react-translate-component](https://github.com/martinandert/react-translate-component)** React component for i18n.
* **[react-bootstrap](https://github.com/stevoland/react-bootstrap)** Bootstrap 3 components built with React
* **[react-topcoat](https://github.com/plaxdan/react-topcoat)** Topcoat components built with React

14
docs/docs/example-apps.md Normal file
View File

@@ -0,0 +1,14 @@
---
id: example-apps
title: Example apps
layout: docs
permalink: example-apps.html
prev: complementary-tools.html
---
Here is a selection of open-source apps built with React.
* **[TodoMVC](https://github.com/tastejs/todomvc/tree/gh-pages/architecture-examples/react/js)**
* **[Khan Academy question editor](https://github.com/khan/perseus)** (browse their GitHub account for many more production apps!)
* **[github-issues-viewer](https://github.com/jaredly/github-issues-viewer)**
* **[hn-react](https://github.com/prabirshrestha/hn-react)** Dead-simple Hacker News client in React

View File

@@ -1,28 +0,0 @@
---
id: examples
title: Examples
layout: docs
permalink: examples.html
prev: complementary-tools.html
---
### Production Apps
* **[Instagram.com](http://instagram.com/)** is 100% built on React, both public site and internal tools.
* **[Facebook.com](http://www.facebook.com/)**'s commenting interface, business management tools, [Lookback video editor](http://facebook.com/lookback/edit), page insights, and most, if not all, new JS development.
* **[Khan Academy](http://khanacademy.org/)** uses React for most new JS development.
* **[Sberbank](http://sberbank.ru/moscow/ru/person/)**, Russia's number one bank, is built with React.
* **[The New York Times's 2014 Red Carpet Project](http://www.nytimes.com/interactive/2014/02/02/fashion/red-carpet-project.html?_r=0)** is built with React.
### Sample Code
* **[React starter kit](/react/downloads.html)** Includes several examples which you can [view online in our GitHub repository](https://github.com/facebook/react/tree/master/examples/).
* **[React one-hour email](https://github.com/petehunt/react-one-hour-email/commits/master)** Goes step-by-step from a static HTML mock to an interactive email reader, written in just one hour!
* **[React server rendering example](https://github.com/mhart/react-server-example)** Demonstrates how to use React's server rendering capabilities.
### Open-Source Demos
* **[TodoMVC](https://github.com/tastejs/todomvc/tree/gh-pages/architecture-examples/react/js)**
* **[Khan Academy question editor](https://github.com/khan/perseus)** (Browse their GitHub account for many more production apps!)
* **[github-issue-viewer](https://github.com/jaredly/github-issues-viewer)**
* **[hn-react](https://github.com/prabirshrestha/hn-react)** Dead-simple Hacker News client.

View File

@@ -11,35 +11,6 @@ next: component-api.html
`React` is the entry point to the React framework. If you're using one of the prebuilt packages it's available as a global; if you're using CommonJS modules you can `require()` it.
### React.Children
`React.Children` provides utilities for dealing with the `this.props.children` opaque data structure.
#### React.Children.map
```javascript
object React.Children.map(object children, function fn [, object context])
```
Invoke `fn` on every immediate child contained within `children` with `this` set to `context`. If `children` is a nested object or array it will be traversed: `fn` will never be passed the container objects. If children is `null` or `undefined` returns `null` or `undefined` rather than an empty object.
#### React.Children.forEach
```javascript
React.Children.forEach(object children, function fn [, object context])
```
Like `React.Children.map()` but does not return an object.
#### React.Children.only
```javascript
object React.Children.only(object children)
```
Return the only child in `children`. Throws otherwise.
### React.DOM
`React.DOM` provides all of the standard HTML tags needed to build a React app. You generally don't use it directly; instead, just include it as part of the `/** @jsx React.DOM */` docblock.
@@ -98,18 +69,9 @@ Remove a mounted React component from the DOM and clean up its event handlers an
### React.renderComponentToString
```javascript
string renderComponentToString(ReactComponent component)
renderComponentToString(ReactComponent component, function callback)
```
Render a component to its initial HTML. This should only be used on the server. React will return an HTML string. You can use this method to generate HTML on the server and send the markup down on the initial request for faster page loads and to allow search engines to crawl your pages for SEO purposes.
Render a component to its initial HTML. This should only be used on the server. React will call `callback` with an HTML string when the markup is ready. You can use this method to can generate HTML on the server and send the markup down on the initial request for faster page loads and to allow search engines to crawl your pages for SEO purposes.
If you call `React.renderComponent()` on a node that already has this server-rendered markup, React will preserve it and only attach event handlers, allowing you to have a very performant first-load experience.
### React.renderComponentToStaticMarkup
```javascript
string renderComponentToStaticMarkup(ReactComponent component)
```
Similar to `renderComponentToString`, except this doesn't create extra DOM attributes such as `data-react-id`, that React uses internally. This is useful if you want to use React as a simple static page generator, as stripping away the extra attributes can save lots of bytes.

View File

@@ -67,31 +67,6 @@ The `mixins` array allows you to use mixins to share behavior among multiple com
<!-- TODO: Document mixins here directly. -->
### statics
```javascript
object statics
```
The `statics` object allows you to define static methods that can be called on the component class. For example:
```javascript
var MyComponent = React.createClass({
statics: {
customMethod: function(foo) {
return foo === 'bar';
}
},
render: function() {
}
});
MyComponent.customMethod('bar'); // true
```
Methods defined within this block are _static_, meaning that you can run them before any component instances are created, and the methods do not have access to the props or state of your components. If you want to check the value of props in a static method, have the caller pass in the props as an argument to the static method.
### displayName
```javascript
@@ -118,17 +93,13 @@ Invoked once, immediately before the initial rendering occurs. If you call `setS
### Mounting: componentDidMount
```javascript
componentDidMount()
componentDidMount(DOMElement rootNode)
```
Invoked immediately after rendering occurs. At this point in the lifecycle, the component has a DOM representation which you can access via `this.getDOMNode()`.
Invoked immediately after rendering occurs. At this point in the lifecycle, the component has a DOM representation which you can access via the `rootNode` argument or by calling `this.getDOMNode()`.
If you want to integrate with other JavaScript frameworks, set timers using `setTimeout` or `setInterval`, or send AJAX requests, perform those operations in this method.
> Note:
>
> Prior to v0.9, the DOM node was passed in as the last argument. If you were using this, you can still access the DOM node by calling `this.getDOMNode()`.
### Updating: componentWillReceiveProps
@@ -195,17 +166,13 @@ Use this as an opportunity to perform preparation before an update occurs.
### Updating: componentDidUpdate
```javascript
componentDidUpdate(object prevProps, object prevState)
componentDidUpdate(object prevProps, object prevState, DOMElement rootNode)
```
Invoked immediately after updating occurs. This method is not called for the initial render.
Use this as an opportunity to operate on the DOM when the component has been updated.
> Note:
>
> Prior to v0.9, the DOM node was passed in as the last argument. If you were using this, you can still access the DOM node by calling `this.getDOMNode()`.
### Unmounting: componentWillUnmount

View File

@@ -19,11 +19,11 @@ The following HTML elements are supported:
a abbr address area article aside audio b base bdi bdo big blockquote body br
button canvas caption cite code col colgroup data datalist dd del details dfn
div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6
head header hr html i iframe img input ins kbd keygen label legend li link
main map mark menu menuitem meta meter nav noscript object ol optgroup option
output p param pre progress q rp rt ruby s samp script section select small
source span strong style sub summary sup table tbody td textarea tfoot th
thead time title tr track u ul var video wbr
head header hr html i iframe img input ins kbd keygen label legend li link main
map mark menu menuitem meta meter nav noscript object ol optgroup option output
p param pre progress q rp rt ruby s samp script section select small source
span strong style sub summary sup table tbody td textarea tfoot th thead time
title tr track u ul var video wbr
```
### SVG elements
@@ -31,8 +31,7 @@ thead time title tr track u ul var video wbr
The following SVG elements are supported:
```
circle defs g line linearGradient path polygon polyline radialGradient rect
stop svg text
circle g line path polygon polyline rect svg text
```
You may also be interested in [react-art](https://github.com/facebook/react-art), a drawing library for React that can render to Canvas, SVG, or VML (for IE8).
@@ -50,28 +49,25 @@ For a list of events, see [Supported Events](/react/docs/events.html).
### HTML Attributes
These standard attributes are supported:
```
accept accessKey action allowFullScreen allowTransparency alt async
accept accessKey action allowFullScreen allowTransparency alt autoCapitalize
autoComplete autoFocus autoPlay cellPadding cellSpacing charSet checked
className colSpan cols content contentEditable contextMenu controls data
dateTime defer dir disabled draggable encType form formNoValidate frameBorder
height hidden href htmlFor httpEquiv icon id label lang list loop max
maxLength method min multiple name noValidate pattern placeholder poster
preload radioGroup readOnly rel required role rowSpan rows sandbox scope
scrollLeft scrollTop seamless selected size span spellCheck src srcDoc step
style tabIndex target title type value width wmode
className colSpan content contentEditable contextMenu controls data dateTime
dir disabled draggable encType form frameBorder height hidden href htmlFor
httpEquiv icon id label lang list loop max maxLength method min multiple name
pattern placeholder poster preload radioGroup readOnly rel required role
rowSpan scrollLeft scrollTop selected size spellCheck src step style tabIndex
target title type value width wmode
```
In addition, the non-standard `autoCapitalize` and `autoCorrect` attributes are supported for Mobile Safari, and the `property` attribute is supported for Open Graph `<meta>` tags.
The non-standard `autoCapitalize` attribute is supported for Mobile Safari.
There is also the React-specific attribute `dangerouslySetInnerHTML` ([more here](/react/docs/special-non-dom-attributes.html)), used for directly inserting HTML strings into a component.
In addition, there is the React-specific attribute `dangerouslySetInnerHTML` ([more here](/react/docs/special-non-dom-attributes.html)), used for directly inserting DOM strings into a component.
### SVG Attributes
```
cx cy d fill fx fy gradientTransform gradientUnits offset points r rx ry
spreadMethod stopColor stopOpacity stroke strokeLinecap strokeWidth textAnchor transform
spreadMethod stopColor stopOpacity stroke strokeLinecap strokeWidth transform
version viewBox x1 x2 x y1 y2 y
```

View File

@@ -108,7 +108,7 @@ Event names:
```
onClick onDoubleClick onDrag onDragEnd onDragEnter onDragExit onDragLeave
onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave
onMouseMove onMouseOut onMouseOver onMouseUp
onMouseMove onMouseUp
```
Properties:

View File

@@ -9,7 +9,7 @@ next: special-non-dom-attributes.html
React has implemented a browser-independent events and DOM system for performance and cross-browser compatibility reasons. We took the opportunity to clean up a few rough edges in browser DOM implementations.
* All DOM properties and attributes (including event handlers) should be camelCased to be consistent with standard JavaScript style. We intentionally break with the spec here since the spec is inconsistent. **However**, `data-*` and `aria-*` attributes [conform to the specs](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#data-*) and should be lower-cased only.
* All DOM properties and attributes (including event handlers) should be camelCased to be consistent with standard JavaScript style. We intentionally break with the spec here since the spec is inconsistent.
* The `style` attribute accepts a JavaScript object with camelCased properties rather than a CSS string. This is consistent with the DOM `style` JavaScript property, is more efficient, and prevents XSS security holes.
* All event objects conform to the W3C spec, and all events (including submit) bubble correctly per the W3C spec. See [Event System](/react/docs/events.html) for more details.
* The `onChange` event behaves as you would expect it to: whenever a form field is changed this event is fired rather than inconsistently on blur. We intentionally break from existing browser behavior because `onChange` is a misnomer for its behavior and React relies on this event to react to user input in real time. See [Forms](/react/docs/forms.html) for more details.

View File

@@ -1,147 +0,0 @@
---
id: thinking-in-react
title: Thinking in React
layout: docs
prev: tutorial.html
next: videos.html
---
This was originally a [blog post](/react/blog/2013/11/05/thinking-in-react.html) from the [official React blog](/react/blog).
React is, in my opinion, the premier way to build big, fast Web apps with JavaScript. It's scaled very well for us at Facebook and Instagram.
One of the many great parts of React is how it makes you think about apps as you build them. In this post I'll walk you through the thought process of building a searchable product data table using React.
## Start with a mock
Imagine that we already have a JSON API and a mock from our designer. Our designer apparently isn't very good because the mock looks like this:
![Mockup](/react/img/blog/thinking-in-react-mock.png)
Our JSON API returns some data that looks like this:
```
[
{category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
{category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
{category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
{category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
{category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
{category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
];
```
## Step 1: break the UI into a component hierarchy
The first thing you'll want to do is to draw boxes around every component (and subcomponent) in the mock and give them all names. If you're working with a designer they may have already done this, so go talk to them! Their Photoshop layer names may end up being the names of your React components!
But how do you know what should be its own component? Just use the same techniques for deciding if you should create a new function or object. One such technique is the [single responsibility principle](http://en.wikipedia.org/wiki/Single_responsibility_principle), that is, a component should ideally only do one thing. If it ends up growing it should be decomposed into smaller subcomponents.
Since you're often displaying a JSON data model to a user, you'll find that if your model was built correctly your UI (and therefore your component structure) will map nicely onto it. That's because user interfaces and data models tend to adhere to the same *information architecture* which means the work of separating your UI into components is often trivial. Just break it up into components that represent exactly one piece of your data model.
![Component diagram](/react/img/blog/thinking-in-react-components.png)
You'll see here that we have five components in our simple app. I've italicized the data each component represents.
1. **`FilterableProductTable` (orange):** contains the entirety of the example
2. **`SearchBar` (blue):** receives all *user input*
3. **`ProductTable` (green):** displays and filters the *data collection* based on *user input*
4. **`ProductCategoryRow` (turquoise):** displays a heading for each *category*
5. **`ProductRow` (red):** displays a row for each *product*
If you look at `ProductTable` you'll see that the table header (containing the "Name" and "Price" labels) isn't its own component. This is a matter of preference and there's an argument to be made either way. For this example I left it as part of `ProductTable` because it is part of rendering the *data collection* which is `ProductTable`'s responsibility. However if this header grows to be complex (i.e. if we were to add affordances for sorting) it would certainly make sense to make this its own `ProductTableHeader` component.
Now that we've identified the components in our mock, let's arrange them into a hierarchy. This is easy. Components that appear within another component in the mock should appear as a child in the hierarchy:
* `FilterableProductTable`
* `SearchBar`
* `ProductTable`
* `ProductCategoryRow`
* `ProductRow`
## Step 2: Build a static version in React
<iframe width="100%" height="300" src="http://jsfiddle.net/6wQMG/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
Now that you have your component hierarchy it's time to start implementing your app. The easiest way is to build a version that takes your data model and renders the UI but has no interactivity. It's easiest to decouple these processes because building a static version requires a lot of typing and no thinking, and adding interactivity requires a lot of thinking and not a lot of typing. We'll see why.
To build a static version of your app that renders your data model you'll want to build components that reuse other components and pass data using *props*. *props* are a way of passing data from parent to child. If you're familiar with the concept of *state*, **don't use state at all** to build this static version. State is reserved only for interactivity, that is, data that changes over time. Since this is a static version of the app you don't need it.
You can build top-down or bottom-up. That is, you can either start with building the components higher up in the hierarchy (i.e. starting with `FilterableProductTable`) or with the ones lower in it (`ProductRow`). In simpler examples it's usually easier to go top-down and on larger projects it's easier to go bottom-up and write tests as you build.
At the end of this step you'll have a library of reusable components that render your data model. The components will only have `render()` methods since this is a static version of your app. The component at the top of the hierarchy (`FilterableProductTable`) will take your data model as a prop. If you make a change to your underlying data model and call `renderComponent()` again the UI will be updated. It's easy to see how your UI is updated and where to make changes since there's nothing complicated going on since React's **one-way data flow** (also called *one-way binding*) keeps everything modular, easy to reason about, and fast.
Simply refer to the [React docs](http://facebook.github.io/react/docs/) if you need help executing this step.
### A brief interlude: props vs state
There are two types of "model" data in React: props and state. It's important to understand the distinction between the two; skim [the official React docs](http://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html) if you aren't sure what the difference is.
## Step 3: Identify the minimal (but complete) representation of UI state
To make your UI interactive you need to be able to trigger changes to your underlying data model. React makes this easy with **state**.
To build your app correctly you first need to think of the minimal set of mutable state that your app needs. The key here is DRY: *Don't Repeat Yourself*. Figure out what the absolute minimal representation of the state of your application needs to be and compute everything else you need on-demand. For example, if you're building a TODO list, just keep an array of the TODO items around; don't keep a separate state variable for the count. Instead, when you want to render the TODO count simply take the length of the TODO items array.
Think of all of the pieces of data in our example application. We have:
* The original list of products
* The search text the user has entered
* The value of the checkbox
* The filtered list of products
Let's go through each one and figure out which one is state. Simply ask three questions about each piece of data:
1. Is it passed in from a parent via props? If so, it probably isn't state.
2. Does it change over time? If not, it probably isn't state.
3. Can you compute it based on any other state or props in your component? If so, it's not state.
The original list of products is passed in as props, so that's not state. The search text and the checkbox seem to be state since they change over time and can't be computed from anything. And finally, the filtered list of products isn't state because it can be computed by combining the original list of products with the search text and value of the checkbox.
So finally, our state is:
* The search text the user has entered
* The value of the checkbox
## Step 4: Identify where your state should live
<iframe width="100%" height="300" src="http://jsfiddle.net/QvHnx/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
OK, so we've identified what the minimal set of app state is. Next we need to identify which component mutates, or *owns*, this state.
Remember: React is all about one-way data flow down the component hierarchy. It may not be immediately clear which component should own what state. **This is often the most challenging part for newcomers to understand,** so follow these steps to figure it out:
For each piece of state in your application:
* Identify every component that renders something based on that state.
* Find a common owner component (a single component above all the components that need the state in the hierarchy).
* Either the common owner or another component higher up in the hierarchy should own the state.
* If you can't find a component where it makes sense to own the state, create a new component simply for holding the state and add it somewhere in the hierarchy above the common owner component.
Let's run through this strategy for our application:
* `ProductTable` needs to filter the product list based on state and `SearchBar` needs to display the search text and checked state.
* The common owner component is `FilterableProductTable`.
* It conceptually makes sense for the filter text and checked value to live in `FilterableProductTable`
Cool, so we've decided that our state lives in `FilterableProductTable`. First, add a `getInitialState()` method to `FilterableProductTable` that returns `{filterText: '', inStockOnly: false}` to reflect the initial state of your application. Then pass `filterText` and `inStockOnly` to `ProductTable` and `SearchBar` as a prop. Finally, use these props to filter the rows in `ProductTable` and set the values of the form fields in `SearchBar`.
You can start seeing how your application will behave: set `filterText` to `"ball"` and refresh your app. You'll see the data table is updated correctly.
## Step 5: Add inverse data flow
<iframe width="100%" height="300" src="http://jsfiddle.net/3Vs3Q/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
So far we've built an app that renders correctly as a function of props and state flowing down the hierarchy. Now it's time to support data flowing the other way: the form components deep in the hierarchy need to update the state in `FilterableProductTable`.
React makes this data flow explicit to make it easy to understand how your program works, but it does require a little more typing than traditional two-way data binding. React provides an add-on called `ReactLink` to make this pattern as convenient as two-way binding, but for the purpose of this post we'll keep everything explicit.
If you try to type or check the box in the current version of the example you'll see that React ignores your input. This is intentional, as we've set the `value` prop of the `input` to always be equal to the `state` passed in from `FilterableProductTable`.
Let's think about what we want to happen. We want to make sure that whenever the user changes the form we update the state to reflect the user input. Since components should only update their own state, `FilterableProductTable` will pass a callback to `SearchBar` that will fire whenever the state should be updated. We can use the `onChange` event on the inputs to be notified of it. And the callback passed by `FilterableProductTable` will call `setState()` and the app will be updated.
Though this sounds like a lot it's really just a few lines of code. And it's really explicit how your data is flowing throughout the app.
## And that's it
Hopefully this gives you an idea of how to think about building components and applications with React. While it may be a little more typing than you're used to, remember that code is read far more than it's written, and it's extremely easy to read this modular, explicit code. As you start to build large libraries of components you'll appreciate this explicitness and modularity, and with code reuse your lines of code will start to shrink :)

View File

@@ -3,10 +3,10 @@ id: tutorial
title: Tutorial
layout: docs
prev: getting-started.html
next: thinking-in-react.html
next: videos.html
---
We'll be building a simple, but realistic comments box that you can drop into a blog, a basic version of the realtime comments offered by Disqus, LiveFyre or Facebook comments.
We'll be building a simple, but realistic comments box that you can drop into a blog, similar to Disqus, LiveFyre or Facebook comments.
We'll provide:
@@ -210,13 +210,12 @@ Markdown is a simple way to format your text inline. For example, surrounding te
First, add the third-party **Showdown** library to your application. This is a JavaScript library which takes Markdown text and converts it to raw HTML. This requires a script tag in your head (which we have already included in the React playground):
```html{7}
```html{6}
<!-- template.html -->
<head>
<title>Hello React</title>
<script src="http://fb.me/react-{{site.react_version}}.js"></script>
<script src="http://fb.me/JSXTransformer-{{site.react_version}}.js"></script>
<script src="http://code.jquery.com/jquery-1.10.0.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/showdown/0.3.1/showdown.min.js"></script>
</head>
```
@@ -304,7 +303,7 @@ React.renderComponent(
Now that the data is available in the `CommentList`, let's render the comments dynamically:
```javascript{4-6,9}
```javascript{4-6}
// tutorial10.js
var CommentList = React.createClass({
render: function() {
@@ -387,13 +386,13 @@ var CommentBox = React.createClass({
},
componentWillMount: function() {
$.ajax({
url: this.props.url,
url: 'comments.json',
dataType: 'json',
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
console.error("comments.json", status, err.toString());
}.bind(this)
});
},
@@ -409,7 +408,7 @@ var CommentBox = React.createClass({
});
```
Here, `componentWillMount` is a method called automatically by React before a component is rendered. The key to dynamic updates is the call to `this.setState()`. We replace the old array of comments with the new one from the server and the UI automatically updates itself. Because of this reactivity, it is only a minor change to add live updates. We will use simple polling here but you could easily use WebSockets or other technologies.
Here, `componentWillMount` is a method called automatically by React before a component is rendered. The key to dynamic updates is the call to `this.setState()`. We replace the old array of comments with the new one from the server and the UI automatically updates itself. Because of this reactivity, it is trivial to add live updates. We will use simple polling here but you could easily use WebSockets or other technologies.
```javascript{3,16-17,31}
// tutorial14.js

View File

@@ -3,7 +3,7 @@ id: videos
title: Videos
layout: docs
permalink: videos.html
prev: thinking-in-react.html
prev: tutorial.html
next: complementary-tools.html
---
@@ -13,39 +13,6 @@ next: complementary-tools.html
"At Facebook and Instagram, were trying to push the limits of whats possible on the web with React. My talk will start with a brief introduction to the framework, and then dive into three controversial topics: Throwing out the notion of templates and building views with JavaScript, “re-rendering” your entire application when your data changes, and a lightweight implementation of the DOM and events." -- [Pete Hunt](http://www.petehunt.net/)
### CodeWinds
[Pete Hunt](http://www.petehunt.net/) talked with [Jeff Barczewski](http://jeff.barczewski.com/) about React in CodeWinds Episode 4.
<figure>[![](/react/img/docs/codewinds-004.png)](http://codewinds.com/4)</figure>
<table width="100%"><tr><td>
02:08 - What is React and why use it?<br />
03:08 - The symbiotic relationship of ClojureScript and React<br />
04:54 - The history of React and why it was created<br />
09:43 - Updating web page with React without using data binding<br />
13:11 - Using the virtual DOM to change the browser DOM<br />
13:57 - Programming with React, render targets HTML, canvas, other<br />
16:45 - Working with designers. Contrasted with Ember and AngularJS<br />
21:45 - JSX Compiler bridging HTML and React javascript<br />
23:50 - Autobuilding JSX and in browser tools for React<br />
24:50 - Tips and tricks to working with React, getting started<br />
</td><td>
27:17 - Rendering HTML on the server with Node.js. Rendering backends<br />
29:20 - React evolved through survival of the fittest at Facebook<br />
30:15 - Ideas for having state on server and client, using web sockets.<br />
32:05 - React-multiuser - distributed shared mutable state using Firebase<br />
33:03 - Better debugging with React using the state transitions, replaying events<br />
34:08 - Differences from Web Components<br />
34:25 - Notable companies using React<br />
35:16 - Could a React backend plugin be created to target PDF?<br />
36:30 - Future of React, what's next?<br />
39:38 - Contributing and getting help<br />
</td></tr></table>
[Read the episode notes](http://codewinds.com/4)
### JavaScript Jabber
[Pete Hunt](http://www.petehunt.net/) and [Jordan Walke](https://github.com/jordwalke) talked about React in JavaScript Jabber 73.
@@ -84,7 +51,7 @@ By [Tom Occhino](http://tomocchino.com/) and [Jordan Walke](https://github.com/j
By [Steven Luscher](https://github.com/steveluscher)
### Introduction to React - LAWebSpeed meetup
### Introduction to React - Joe Dev on Tech
<iframe width="650" height="315" src="//www.youtube.com/embed/SMMRJif5QW0" frameborder="0" allowfullscreen></iframe>
@@ -98,4 +65,4 @@ by [Stoyan Stefanov](http://www.phpied.com/)
### "Functional DOM programming" - Meteor DevShop 11
<iframe width="650" height="315" src="//www.youtube.com/embed/qqVbr_LaCIo" frameborder="0" allowfullscreen></iframe>
<iframe width="650" height="315" src="//www.youtube.com/embed/Lqcs6hPOcFw?t=49m23s" frameborder="0" allowfullscreen></iframe>

View File

@@ -57,27 +57,15 @@ The JSX transformer used to support [XML syntax](/react/docs/jsx-in-depth.html)
All scripts are also available via [CDNJS](http://cdnjs.com/libraries/react/).
## npm
To install the JSX transformer on your computer, run:
```sh
$ npm install -g react-tools
```
For more info about the `jsx` binary, see the [Getting Started](/react/docs/getting-started.html#offline-transform) guide.
If you're using an npm-compatible packaging system like browserify or webpack, you can use the `react` package. After installing it using `npm install react` or adding `react` to `package.json`, you can use React:
```js
var React = require('react');
React.renderComponent(...);
```
If you'd like to use any [add-ons](/react/docs/addons.html), use `var React = require('react/addons');` instead.
## Bower
```sh
$ bower install --save react
```
## NPM
```sh
$ npm install -g react-tools
```

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -20,17 +20,10 @@ See [Inline Styles](/react/tips/inline-styles.html) for more info.
Sometimes you _do_ want to keep the CSS properties unitless. Here's a list of properties that won't get the automatic "px" suffix:
- `columnCount`
- `fillOpacity`
- `flex`
- `flexGrow`
- `flexShrink`
- `fontWeight`
- `lineClamp`
- `lineHeight`
- `opacity`
- `order`
- `orphans`
- `widows`
- `zIndex`
- `zoom`

View File

@@ -49,5 +49,3 @@ var GenericWrapper = React.createClass({
React.renderComponent(<GenericWrapper>hello</GenericWrapper>, mountNode);
```
To make `this.props.children` easy to deal with, we've provided the [React.Children utilities](/react/docs/top-level-api.html#react.children).

View File

@@ -1,5 +0,0 @@
# React Examples
Here are some small React demos. Some use [JSX](http://facebook.github.io/react/docs/jsx-in-depth.html) and some include third-party library integration.
For more fully-featured examples, check out [React TodoMVC](http://todomvc.com/architecture-examples/react/) and [React + Backbone TodoMVC](http://todomvc.com/labs/architecture-examples/react-backbone/).

View File

@@ -18,7 +18,9 @@ var BallmerPeakCalculator = React.createClass({
this.setState({bac: event.target.value});
},
render: function() {
var pct = computeBallmerPeak(this.state.bac);
var bac;
var pct;
pct = computeBallmerPeak(this.state.bac);
if (isNaN(pct)) {
pct = 'N/A';
} else {

View File

@@ -2,11 +2,11 @@
<html>
<head>
<meta http-equiv='Content-type' content='text/html; charset=utf-8'>
<title>Ballmer Peak Calculator</title>
<title>Ballmer Peak calculator</title>
<link rel="stylesheet" href="../shared/css/base.css" />
</head>
<body>
<h1>Ballmer Peak Calculator</h1>
<h1>Ballmer Peak calculator</h1>
<div id="container">
<p>
If you can see this, React is not working right. This is probably because you&apos;re viewing
@@ -18,9 +18,19 @@
</p>
</div>
<h4>Example Details</h4>
<p>This is written with JSX in a separate file and transformed in the browser.</p>
<ul>
<li>
This is built with
<a href="https://github.com/substack/node-browserify">browserify</a>.
</li>
<li>
This is written with JSX in a separate file and transformed in the browser.
</li>
</ul>
<p>
Learn more about React at
</p>
<p>
Learn more at
<a href="http://facebook.github.io/react" target="_blank">facebook.github.io/react</a>.
</p>
<script src="../../build/react.js"></script>

View File

@@ -2,27 +2,68 @@
<html>
<head>
<meta http-equiv='Content-type' content='text/html; charset=utf-8'>
<title>Basic Example with External JSX</title>
<title>Basic Example with external JSX</title>
<link rel="stylesheet" href="../shared/css/base.css" />
<style type="text/css" media="screen">
.codeBox {
padding: 7px;
overflow:scroll;
background-color: #eee;
font-weight:normal;
}
</style>
<script type="text/javascript" charset="utf-8">
window.setTimeout(function() {
var chromeClientCLI = window.chromeClientCLI;
var errorBox = window.errorBox;
var chromeErrorFooter = window.chromeErrorFooter;
var chromeInstructions = window.chromeInstructions;
var isChrome = !!window.chrome;
chromeClientCLI.innerText =
'open -a "Google Chrome" --new \\\n' +
' ' + window.location.href + ' \\\n' +
' --args --allow-file-access-from-files --user-data-dir=/tmp';
errorBox.innerText =
isChrome ? 'To run in Chrome, do one of the following:' :
'Errors loading page: Check the console.'
chromeErrorFooter.innerText =
isChrome ? 'If page still does not load, check console.' : '';
if (!isChrome) {
chromeInstructions.innerText = "";
}
}, 0);
</script>
</head>
<body>
<h1>Basic Example with External JSX</h1>
<h1>Basic Example with external JSX</h1>
<div id="container">
<p>
If you can see this, React is not working right. This is probably because you&apos;re viewing
this on your file system instead of a web server. Try running
<pre>
python -m SimpleHTTPServer
</pre>
and going to <a href="http://localhost:8000/">http://localhost:8000/</a>.
<h4 id="errorBox" style="color: #733"></h4>
<ol id="chromeInstructions">
<li>
Open this page on a Mac via the terminal command:
<pre id="chromeClientCLI" class="codeBox">
</li>
<h4><i>OR</i></h4>
<li>
Serve this page from a web server
<pre id="chromeServerCLI" class="codeBox">
cd /Path/To/This/File
python -m SimpleHTTPServer
open -a "Google Chrome" <a href="http://localhost:8000/">http://localhost:8000/</a>. </pre>
</li>
</ol>
<h4 id="chromeErrorFooter" style="color: #733"></h4>
</p>
</div>
<h4>Example Details</h4>
<p>This is written with JSX in a separate file and transformed in the browser.</p>
<p>
Learn more about React at
<a href="http://facebook.github.io/react" target="_blank">facebook.github.io/react</a>.
Example Details: This is built with
<a href="https://github.com/substack/node-browserify">browserify</a>.
A separate JSX file is transformed in the browser.
</p>
<script src="../../build/react.js"></script>
<script src="../../build/JSXTransformer.js"></script>

View File

@@ -2,26 +2,42 @@
<html>
<head>
<meta http-equiv='Content-type' content='text/html; charset=utf-8'>
<title>Basic Example with Precompiled JSX</title>
<title>Basic Example with precompiled JSX</title>
<link rel="stylesheet" href="../shared/css/base.css" />
</head>
<body>
<h1>Basic Example with Precompiled JSX</h1>
<h1>Basic Example with precompiled JSX</h1>
<div id="container">
<p>
If you can see this, React is not running. Try running:
To install React, follow the instructions on
<a href="http://www.github.com/facebook/react/">GitHub</a>.
</p>
<p>
If you can see this, React is not running. You probably didn't run:
<pre>
npm install -g react-tools
jsx . build/
</pre>
</p>
<pre>npm install -g react-tools
cd examples/basic-jsx-precompile/
jsx . build/</pre>
</div>
<h4>Example Details</h4>
<p>This is written with JSX in a separate file and precompiled to vanilla JS by running:</p>
<pre>npm install -g react-tools
cd examples/basic-jsx-precompile/
jsx . build/</pre>
<ul>
<li>
This is built with
<a href="https://github.com/substack/node-browserify">browserify</a>.
</li>
<li>
This is written with JSX and precompiled to vanilla JS by doing:
<pre>
npm install -g react-tools
jsx . build/
</pre>
</li>
</ul>
<p>
Learn more about React at
</p>
<p>
Learn more at
<a href="http://facebook.github.io/react" target="_blank">facebook.github.io/react</a>.
</p>
<script src="../../build/react.js"></script>

View File

@@ -18,9 +18,19 @@
</p>
</div>
<h4>Example Details</h4>
<p>This is written with JSX and transformed in the browser.<p>
<ul>
<li>
This is built with
<a href="https://github.com/substack/node-browserify">browserify</a>.
</li>
<li>
This is written with JSX and transformed in the browser.
</li>
</ul>
<p>
Learn more about React at
</p>
<p>
Learn more at
<a href="http://facebook.github.io/react" target="_blank">facebook.github.io/react</a>.
</p>
<script src="../../build/react.js"></script>

View File

@@ -18,9 +18,16 @@
</p>
</div>
<h4>Example Details</h4>
<p>This is written in vanilla JavaScript (without JSX) and transformed in the browser.<p>
<ul>
<li>
This is built with
<a href="https://github.com/substack/node-browserify">browserify</a>.
</li>
</ul>
<p>
Learn more about React at
</p>
<p>
Learn more at
<a href="http://facebook.github.io/react" target="_blank">facebook.github.io/react</a>.
</p>
<script src="../../build/react.js"></script>

View File

@@ -1,6 +0,0 @@
jQuery Mobile React Example
===========================
This example demonstrates how jQuery Mobile applications can be built with React.
The source code is based on jQuery Mobile's [pages-multi-page example](https://github.com/jquery/jquery-mobile/tree/master/demos/pages-multi-page).

View File

@@ -1,18 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery Mobile React Example</title>
<link rel="stylesheet" href="//code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.min.css" />
<link rel="stylesheet" href="//demos.jquerymobile.com/1.4.0/_assets/css/jqm-demos.css" />
</head>
<body class="ui-mobile-viewport ui-overlay-a">
<div id="content"></div>
<script src="//code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="//code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.min.js"></script>
<script src="../../build/react.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>

View File

@@ -1,178 +0,0 @@
/**
* jQuery Mobile React Example
*
* Main application script.
* For variety, this example is written in 100% JSHint-compliant JavaScript, not in JSX.
*
* Component structure:
*
* - App
* |-- JQueryMobilePage (one)
* | |-- JQueryMobileHeader
* | |-- JQueryMobileContent
* | | |-- PageOneContent
* | | |-- JQueryMobileButton
* | |-- JQueryMobileFooter
* |-- JQueryMobilePage (two)
* | |-- JQueryMobileHeader
* | |-- JQueryMobileContent
* | | |-- PageTwoContent
* | | |-- JQueryMobileButton
* | |-- JQueryMobileFooter
* |-- JQueryMobilePage (popup)
* |-- JQueryMobileHeader
* |-- JQueryMobileContent
* | |-- PagePopUpContent
* | |-- JQueryMobileButton
* |-- JQueryMobileFooter
*/
/* global document, React */
'use strict';
/** Main application component. */
var App = React.createClass({
displayName: 'App',
render: function() {
return React.DOM.div({className:'app'},
JQueryMobilePage({id:'one'}, PageOneContent(null)),
JQueryMobilePage({id:'two'}, PageTwoContent(null)),
JQueryMobilePage({id:'popup', headerTheme:'b'}, PagePopUpContent(null))
);
}
});
/** jQuery Mobile button component. */
var JQueryMobileButton = React.createClass({
displayName: 'JQueryMobileButton',
getDefaultProps: function() {
return {className:'ui-btn ui-shadow ui-corner-all'};
},
render: function() {
return React.DOM.p(null,
React.DOM.a(this.props, this.props.children)
);
}
});
/** jQuery Mobile page content component. */
var JQueryMobileContent = React.createClass({
displayName: 'JQueryMobileContent',
render: function() {
return React.DOM.div({role:'main', className:'ui-content'},
this.props.children
);
}
});
/** jQuery Mobile footer component. */
var JQueryMobileFooter = React.createClass({
displayName: 'JQueryMobileFooter',
render: function() {
return React.DOM.div({'data-role':'footer'},
React.DOM.h4(null, 'Page footer')
);
}
});
/** jQuery Mobile header component. */
var JQueryMobileHeader = React.createClass({
displayName: 'JQueryMobileHeader',
render: function() {
return React.DOM.div({'data-role':'header', 'data-theme':this.props.headerTheme},
React.DOM.h1(null, this.props.title)
);
}
});
/** jQuery Mobile page component. */
var JQueryMobilePage = React.createClass({
displayName: 'JQueryMobilePage',
getDefaultProps: function() {
return {'data-role':'page', 'data-theme':'a', headerTheme:'a'};
},
render: function() {
return this.transferPropsTo(React.DOM.div(null,
JQueryMobileHeader({title:'Page ' + this.props.id, headerTheme:this.props.headerTheme}),
JQueryMobileContent(null, this.props.children),
JQueryMobileFooter(null)
));
}
});
/** Application page one component. */
var PageOneContent = React.createClass({
displayName: 'PageOneContent',
render: function() {
return React.DOM.div(null,
React.DOM.h2(null, 'One'),
React.DOM.p(null,
'I have an ',
React.DOM.code(null, 'id'),
' of "one" on my page container. I\'m first in the source order so I\'m shown when the page loads.'
),
React.DOM.p(null, 'This is a multi-page boilerplate template that you can copy to build your first jQuery Mobile page. This template contains multiple "page" containers inside, unlike a single page template that has just one page within it.'),
React.DOM.p(null, 'Just view the source and copy the code to get started. All the CSS and JS is linked to the jQuery CDN versions so this is super easy to set up. Remember to include a meta viewport tag in the head to set the zoom level.'),
React.DOM.p(null,
'You link to internal pages by referring to the ',
React.DOM.code(null, 'id'),
' of the page you want to show. For example, to ',
React.DOM.a({href:'#two'}, 'link'),
' to the page with an ',
React.DOM.code(null, 'id'),
' of "two", my link would have a ',
React.DOM.code(null, 'href="#two"'),
' in the code.'
),
React.DOM.h3(null, 'Show internal pages:'),
JQueryMobileButton({href:'#two'}, 'Show page "two"'),
JQueryMobileButton({href:'#popup', 'data-rel':'dialog', 'data-transition':'pop'}, 'Show page "popup" (as a dialog)')
);
}
});
/** Application page two component. */
var PageTwoContent = React.createClass({
displayName: 'PageTwoContent',
render: function() {
return React.DOM.div(null,
React.DOM.h2(null, 'Two'),
React.DOM.p(null, 'I have an id of "two" on my page container. I\'m the second page container in this multi-page template.'),
React.DOM.p(null, 'Notice that the theme is different for this page because we\'ve added a few ',
React.DOM.code(null, 'data-theme'),
' swatch assigments here to show off how flexible it is. You can add any content or widget to these pages, but we\'re keeping these simple.'),
JQueryMobileButton({href:'#one', 'data-direction':'reverse', className:'ui-btn ui-shadow ui-corner-all ui-btn-b'}, 'Back to page "one"')
);
}
});
/** Application popup page component. */
var PagePopUpContent = React.createClass({
displayName: 'PagePopUpContent',
render: function() {
return React.DOM.div(null,
React.DOM.h2(null, 'Popup'),
React.DOM.p(null, 'I have an id of "popup" on my page container and only look like a dialog because the link to me had a ',
React.DOM.code(null, 'data-rel="dialog"'),
' attribute which gives me this inset look and a ',
React.DOM.code(null, 'data-transition="pop"'),
' attribute to change the transition to pop. Without this, I\'d be styled as a normal page.'),
JQueryMobileButton({href:'#one', 'data-rel':'back', className:'ui-btn ui-shadow ui-corner-all ui-btn-inline ui-icon-back ui-btn-icon-left'}, 'Back to page "one"')
);
}
});
// Render application.
React.renderComponent(App(null), document.getElementById('content'));

View File

@@ -0,0 +1,3 @@
# TodoMVC-Backbone
This is a lightweight version of TodoMVC. Its primary purpose is to demo the Backbone integration rather than being feature-complete (refer to `todomvc-director` for a full TodoMVC-compilant app).

View File

@@ -0,0 +1,556 @@
html,
body {
margin: 0;
padding: 0;
}
button {
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
color: inherit;
-webkit-appearance: none;
/*-moz-appearance: none;*/
-ms-appearance: none;
-o-appearance: none;
appearance: none;
}
body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eaeaea url('bg.png');
color: #4d4d4d;
width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
#todoapp {
background: #fff;
background: rgba(255, 255, 255, 0.9);
margin: 130px 0 40px 0;
border: 1px solid #ccc;
position: relative;
border-top-left-radius: 2px;
border-top-right-radius: 2px;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
#todoapp:before {
content: '';
border-left: 1px solid #f5d6d6;
border-right: 1px solid #f5d6d6;
width: 2px;
position: absolute;
top: 0;
left: 40px;
height: 100%;
}
#todoapp input::-webkit-input-placeholder {
font-style: italic;
}
#todoapp input::-moz-placeholder {
font-style: italic;
color: #a9a9a9;
}
#todoapp h1 {
position: absolute;
top: -120px;
width: 100%;
font-size: 70px;
font-weight: bold;
text-align: center;
color: #b3b3b3;
color: rgba(255, 255, 255, 0.3);
text-shadow: -1px -1px rgba(0, 0, 0, 0.2);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
-ms-text-rendering: optimizeLegibility;
-o-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
#header {
padding-top: 15px;
border-radius: inherit;
}
#header:before {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
height: 15px;
z-index: 2;
border-bottom: 1px solid #6c615c;
background: #8d7d77;
background: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)),to(rgba(101, 84, 76, 0.8)));
background: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: -moz-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: -o-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: -ms-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');
border-top-left-radius: 1px;
border-top-right-radius: 1px;
}
#new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
font-family: inherit;
line-height: 1.4em;
border: 0;
outline: none;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
#new-todo {
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.02);
z-index: 2;
box-shadow: none;
}
#main {
position: relative;
z-index: 2;
border-top: 1px dotted #adadad;
}
label[for='toggle-all'] {
display: none;
}
#toggle-all {
position: absolute;
top: -42px;
left: -4px;
width: 40px;
text-align: center;
border: none; /* Mobile Safari */
}
#toggle-all:before {
content: '»';
font-size: 28px;
color: #d9d9d9;
padding: 0 25px 7px;
}
#toggle-all:checked:before {
color: #737373;
}
#todo-list {
margin: 0;
padding: 0;
list-style: none;
}
#todo-list li {
position: relative;
font-size: 24px;
border-bottom: 1px dotted #ccc;
}
#todo-list li:last-child {
border-bottom: none;
}
#todo-list li.editing {
border-bottom: none;
padding: 0;
}
#todo-list li.editing .edit {
display: block;
width: 506px;
padding: 13px 17px 12px 17px;
margin: 0 0 0 43px;
}
#todo-list li.editing .view {
display: none;
}
#todo-list li .toggle {
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none; /* Mobile Safari */
-webkit-appearance: none;
/*-moz-appearance: none;*/
-ms-appearance: none;
-o-appearance: none;
appearance: none;
}
#todo-list li .toggle:after {
content: '✔';
line-height: 43px; /* 40 + a couple of pixels visual adjustment */
font-size: 20px;
color: #d9d9d9;
text-shadow: 0 -1px 0 #bfbfbf;
}
#todo-list li .toggle:checked:after {
color: #85ada7;
text-shadow: 0 1px 0 #669991;
bottom: 1px;
position: relative;
}
#todo-list li label {
white-space: pre;
word-break: break-word;
padding: 15px 60px 15px 15px;
margin-left: 45px;
display: block;
line-height: 1.2;
-webkit-transition: color 0.4s;
-moz-transition: color 0.4s;
-ms-transition: color 0.4s;
-o-transition: color 0.4s;
transition: color 0.4s;
}
#todo-list li.completed label {
color: #a9a9a9;
text-decoration: line-through;
}
#todo-list li .destroy {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 22px;
color: #a88a8a;
-webkit-transition: all 0.2s;
-moz-transition: all 0.2s;
-ms-transition: all 0.2s;
-o-transition: all 0.2s;
transition: all 0.2s;
}
#todo-list li .destroy:hover {
text-shadow: 0 0 1px #000,
0 0 10px rgba(199, 107, 107, 0.8);
-webkit-transform: scale(1.3);
-moz-transform: scale(1.3);
-ms-transform: scale(1.3);
-o-transform: scale(1.3);
transform: scale(1.3);
}
#todo-list li .destroy:after {
content: '✖';
}
#todo-list li:hover .destroy {
display: block;
}
#todo-list li .edit {
display: none;
}
#todo-list li.editing:last-child {
margin-bottom: -1px;
}
#footer {
color: #777;
padding: 0 15px;
position: absolute;
right: 0;
bottom: -31px;
left: 0;
height: 20px;
z-index: 1;
text-align: center;
}
#footer:before {
content: '';
position: absolute;
right: 0;
bottom: 31px;
left: 0;
height: 50px;
z-index: -1;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3),
0 6px 0 -3px rgba(255, 255, 255, 0.8),
0 7px 1px -3px rgba(0, 0, 0, 0.3),
0 43px 0 -6px rgba(255, 255, 255, 0.8),
0 44px 2px -6px rgba(0, 0, 0, 0.2);
}
#todo-count {
float: left;
text-align: left;
}
#filters {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
#filters li {
display: inline;
}
#filters li a {
color: #83756f;
margin: 2px;
text-decoration: none;
}
#filters li a.selected {
font-weight: bold;
}
#clear-completed {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
background: rgba(0, 0, 0, 0.1);
font-size: 11px;
padding: 0 10px;
border-radius: 3px;
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2);
}
#clear-completed:hover {
background: rgba(0, 0, 0, 0.15);
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
}
#info {
margin: 65px auto 0;
color: #a6a6a6;
font-size: 12px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
text-align: center;
}
#info a {
color: inherit;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox and Opera
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
#toggle-all,
#todo-list li .toggle {
background: none;
}
#todo-list li .toggle {
height: 40px;
}
#toggle-all {
top: -56px;
left: -15px;
width: 65px;
height: 41px;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-appearance: none;
appearance: none;
}
}
.hidden {
display: none;
}
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #C5C5C5;
border-bottom: 1px dashed #F7F7F7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
/**body*/.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
/**body*/.learn-bar {
width: auto;
margin: 0 0 0 300px;
}
/**body*/.learn-bar > .learn {
left: 8px;
}
/**body*/.learn-bar #todoapp {
width: 550px;
margin: 130px auto 40px auto;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,22 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>React • TodoMVC</title>
<link rel="stylesheet" href="css/base.css">
<!--[if IE]>
<script src="js/ie.js"></script>
<![endif]-->
</head>
<body>
<div id="container"></div>
<script src="../../build/react.js"></script>
<script src="../../build/JSXTransformer.js"></script>
<script type="text/javascript" src="../shared/thirdparty/jquery.min.js" charset="utf-8"></script>
<script type="text/javascript" src="thirdparty/lodash.min.js" charset="utf-8"></script>
<script type="text/javascript" src="thirdparty/backbone-min.js" charset="utf-8"></script>
<script type="text/javascript" src="thirdparty/backbone.localStorage-min.js" charset="utf-8"></script>
<script type="text/jsx" src="js/app.js"></script>
</body>
</html>

View File

@@ -0,0 +1,303 @@
/** @jsx React.DOM */
var Todo = Backbone.Model.extend({
// Default attributes for the todo
// and ensure that each todo created has `title` and `completed` keys.
defaults: {
title: '',
completed: false
},
// Toggle the `completed` state of this todo item.
toggle: function() {
this.save({
completed: !this.get('completed')
});
}
});
var TodoList = Backbone.Collection.extend({
// Reference to this collection's model.
model: Todo,
// Save all of the todo items under the `"todos"` namespace.
localStorage: new Store('todos-react-backbone'),
// Filter down the list of all todo items that are finished.
completed: function() {
return this.filter(function( todo ) {
return todo.get('completed');
});
},
remaining: function() {
return this.without.apply(this, this.completed());
},
// We keep the Todos in sequential order, despite being saved by unordered
// GUID in the database. This generates the next order number for new items.
nextOrder: function () {
if (!this.length) {
return 1;
}
return this.last().get('order') + 1;
},
// Todos are sorted by their original insertion order.
comparator: function (todo) {
return todo.get('order');
}
});
var Utils = {
pluralize: function( count, word ) {
return count === 1 ? word : word + 's';
},
stringifyObjKeys: function(obj) {
var s = '';
for (var key in obj) {
if (!obj.hasOwnProperty(key)) {
continue;
}
if (obj[key]) {
s += key + ' ';
}
}
return s;
}
};
// Begin React stuff
var TodoItem = React.createClass({
handleSubmit: function(event) {
var val = this.refs.editField.getDOMNode().value.trim();
if (val) {
this.props.onSave(val);
} else {
this.props.onDestroy();
}
return false;
},
onEdit: function() {
this.props.onEdit();
this.refs.editField.getDOMNode().focus();
},
render: function() {
var classes = Utils.stringifyObjKeys({
completed: this.props.todo.get('completed'), editing: this.props.editing
});
return (
<li className={classes}>
<div className="view">
<input
className="toggle"
type="checkbox"
checked={this.props.todo.get('completed')}
onChange={this.props.onToggle}
key={this.props.key}
/>
<label onDoubleClick={this.onEdit}>
{this.props.todo.get('title')}
</label>
<button className="destroy" onClick={this.props.onDestroy} />
</div>
<form onSubmit={this.handleSubmit}>
<input
ref="editField"
className="edit"
defaultValue={this.props.todo.get('title')}
onBlur={this.handleSubmit}
autoFocus="autofocus"
/>
</form>
</li>
);
}
});
var TodoFooter = React.createClass({
render: function() {
var activeTodoWord = Utils.pluralize(this.props.count, 'todo');
var clearButton = null;
if (this.props.completedCount > 0) {
clearButton = (
<button id="clear-completed" onClick={this.props.onClearCompleted}>
Clear completed ({this.props.completedCount})
</button>
);
}
return (
<footer id="footer">
<span id="todo-count">
<strong>{this.props.count}</strong>{' '}
{activeTodoWord}{' '}left
</span>
{clearButton}
</footer>
);
}
});
// An example generic Mixin that you can add to any component that should react
// to changes in a Backbone component. The use cases we've identified thus far
// are for Collections -- since they trigger a change event whenever any of
// their constituent items are changed there's no need to reconcile for regular
// models. One caveat: this relies on getBackboneModels() to always return the
// same model instances throughout the lifecycle of the component. If you're
// using this mixin correctly (it should be near the top of your component
// hierarchy) this should not be an issue.
var BackboneMixin = {
componentDidMount: function() {
// Whenever there may be a change in the Backbone data, trigger a reconcile.
this.getBackboneModels().forEach(function(model) {
model.on('add change remove', this.forceUpdate.bind(this, null), this);
}, this);
},
componentWillUnmount: function() {
// Ensure that we clean up any dangling references when the component is
// destroyed.
this.getBackboneModels().forEach(function(model) {
model.off(null, null, this);
}, this);
}
};
var TodoApp = React.createClass({
mixins: [BackboneMixin],
getInitialState: function() {
return {editing: null};
},
componentDidMount: function() {
// Additional functionality for todomvc: fetch() the collection on init
this.props.todos.fetch();
this.refs.newField.getDOMNode().focus();
},
componentDidUpdate: function() {
// If saving were expensive we'd listen for mutation events on Backbone and
// do this manually. however, since saving isn't expensive this is an
// elegant way to keep it reactively up-to-date.
this.props.todos.forEach(function(todo) {
todo.save();
});
},
getBackboneModels: function() {
return [this.props.todos];
},
handleSubmit: function(event) {
event.preventDefault();
var val = this.refs.newField.getDOMNode().value.trim();
if (val) {
this.props.todos.create({
title: val,
completed: false,
order: this.props.todos.nextOrder()
});
this.refs.newField.getDOMNode().value = '';
}
},
toggleAll: function(event) {
var checked = event.nativeEvent.target.checked;
this.props.todos.forEach(function(todo) {
todo.set('completed', checked);
});
},
edit: function(todo) {
this.setState({editing: todo.get('id')});
},
save: function(todo, text) {
todo.set('title', text);
this.setState({editing: null});
},
clearCompleted: function() {
this.props.todos.completed().forEach(function(todo) {
todo.destroy();
});
},
render: function() {
var footer = null;
var main = null;
var todoItems = this.props.todos.map(function(todo) {
return (
<TodoItem
key={Math.random()}
todo={todo}
onToggle={todo.toggle.bind(todo)}
onDestroy={todo.destroy.bind(todo)}
onEdit={this.edit.bind(this, todo)}
editing={this.state.editing === todo.get('id')}
onSave={this.save.bind(this, todo)}
/>
);
}, this);
var activeTodoCount = this.props.todos.remaining().length;
var completedCount = todoItems.length - activeTodoCount;
if (activeTodoCount || completedCount) {
footer =
<TodoFooter
count={activeTodoCount}
completedCount={completedCount}
onClearCompleted={this.clearCompleted}
/>;
}
if (todoItems.length) {
main = (
<section id="main">
<input id="toggle-all" type="checkbox" onChange={this.toggleAll} />
<ul id="todo-list">
{todoItems}
</ul>
</section>
);
}
return (
<div>
<section id="todoapp">
<header id="header">
<h1>todos</h1>
<form onSubmit={this.handleSubmit}>
<input
ref="newField"
id="new-todo"
placeholder="What needs to be done?"
/>
</form>
</header>
{main}
{footer}
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>
Created by{' '}
<a href="http://github.com/petehunt/">petehunt</a>
</p>
<p>Part of{' '}<a href="http://todomvc.com">TodoMVC</a></p>
</footer>
</div>
);
}
});
React.renderComponent(
<TodoApp todos={new TodoList()} />, document.getElementById('container')
);

View File

@@ -0,0 +1,34 @@
/*! HTML5 Shiv pre3.6 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
Uncompressed source: https://github.com/aFarkas/html5shiv */
(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();
a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x<style>article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}</style>";
c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="<xyz></xyz>";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||
"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment();
for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d<h;d++)c.createElement(e[d]);return c}};l.html5=e;q(f)})(this,document);
/* ES5-shim
https://github.com/kriskowal/es5-shim
Copyright 2009-2012 by contributors, MIT License */
(function(definition){if(typeof define=="function")define(definition);else if(typeof YUI=="function")YUI.add("es5",definition);else definition()})(function(){if(!Function.prototype.bind)Function.prototype.bind=function bind(that){var target=this;if(typeof target!="function")throw new TypeError("Function.prototype.bind called on incompatible "+target);var args=slice.call(arguments,1);var bound=function(){if(this instanceof bound){var result=target.apply(this,args.concat(slice.call(arguments)));if(Object(result)===
result)return result;return this}else return target.apply(that,args.concat(slice.call(arguments)))};if(target.prototype)bound.prototype=Object.create(target.prototype);return bound};var call=Function.prototype.call;var prototypeOfArray=Array.prototype;var prototypeOfObject=Object.prototype;var slice=prototypeOfArray.slice;var _toString=call.bind(prototypeOfObject.toString);var owns=call.bind(prototypeOfObject.hasOwnProperty);var defineGetter;var defineSetter;var lookupGetter;var lookupSetter;var supportsAccessors;
if(supportsAccessors=owns(prototypeOfObject,"__defineGetter__")){defineGetter=call.bind(prototypeOfObject.__defineGetter__);defineSetter=call.bind(prototypeOfObject.__defineSetter__);lookupGetter=call.bind(prototypeOfObject.__lookupGetter__);lookupSetter=call.bind(prototypeOfObject.__lookupSetter__)}if([1,2].splice(0).length!=2){var array_splice=Array.prototype.splice;Array.prototype.splice=function(start,deleteCount){if(!arguments.length)return[];else return array_splice.apply(this,[start===void 0?
0:start,deleteCount===void 0?this.length-start:deleteCount].concat(slice.call(arguments,2)))}}if(!Array.isArray)Array.isArray=function isArray(obj){return _toString(obj)=="[object Array]"};var boxedString=Object("a"),splitString=boxedString[0]!="a"||!(0 in boxedString);if(!Array.prototype.forEach)Array.prototype.forEach=function forEach(fun){var object=toObject(this),self=splitString&&_toString(this)=="[object String]"?this.split(""):object,thisp=arguments[1],i=-1,length=self.length>>>0;if(_toString(fun)!=
"[object Function]")throw new TypeError;while(++i<length)if(i in self)fun.call(thisp,self[i],i,object)};if(!Array.prototype.map)Array.prototype.map=function map(fun){var object=toObject(this),self=splitString&&_toString(this)=="[object String]"?this.split(""):object,length=self.length>>>0,result=Array(length),thisp=arguments[1];if(_toString(fun)!="[object Function]")throw new TypeError(fun+" is not a function");for(var i=0;i<length;i++)if(i in self)result[i]=fun.call(thisp,self[i],i,object);return result};
if(!Array.prototype.filter)Array.prototype.filter=function filter(fun){var object=toObject(this),self=splitString&&_toString(this)=="[object String]"?this.split(""):object,length=self.length>>>0,result=[],value,thisp=arguments[1];if(_toString(fun)!="[object Function]")throw new TypeError(fun+" is not a function");for(var i=0;i<length;i++)if(i in self){value=self[i];if(fun.call(thisp,value,i,object))result.push(value)}return result};if(!Array.prototype.every)Array.prototype.every=function every(fun){var object=
toObject(this),self=splitString&&_toString(this)=="[object String]"?this.split(""):object,length=self.length>>>0,thisp=arguments[1];if(_toString(fun)!="[object Function]")throw new TypeError(fun+" is not a function");for(var i=0;i<length;i++)if(i in self&&!fun.call(thisp,self[i],i,object))return false;return true};if(!Array.prototype.some)Array.prototype.some=function some(fun){var object=toObject(this),self=splitString&&_toString(this)=="[object String]"?this.split(""):object,length=self.length>>>
0,thisp=arguments[1];if(_toString(fun)!="[object Function]")throw new TypeError(fun+" is not a function");for(var i=0;i<length;i++)if(i in self&&fun.call(thisp,self[i],i,object))return true;return false};if(!Array.prototype.reduce)Array.prototype.reduce=function reduce(fun){var object=toObject(this),self=splitString&&_toString(this)=="[object String]"?this.split(""):object,length=self.length>>>0;if(_toString(fun)!="[object Function]")throw new TypeError(fun+" is not a function");if(!length&&arguments.length==
1)throw new TypeError("reduce of empty array with no initial value");var i=0;var result;if(arguments.length>=2)result=arguments[1];else{do{if(i in self){result=self[i++];break}if(++i>=length)throw new TypeError("reduce of empty array with no initial value");}while(true)}for(;i<length;i++)if(i in self)result=fun.call(void 0,result,self[i],i,object);return result};if(!Array.prototype.reduceRight)Array.prototype.reduceRight=function reduceRight(fun){var object=toObject(this),self=splitString&&_toString(this)==
"[object String]"?this.split(""):object,length=self.length>>>0;if(_toString(fun)!="[object Function]")throw new TypeError(fun+" is not a function");if(!length&&arguments.length==1)throw new TypeError("reduceRight of empty array with no initial value");var result,i=length-1;if(arguments.length>=2)result=arguments[1];else{do{if(i in self){result=self[i--];break}if(--i<0)throw new TypeError("reduceRight of empty array with no initial value");}while(true)}do if(i in this)result=fun.call(void 0,result,
self[i],i,object);while(i--);return result};if(!Array.prototype.indexOf||[0,1].indexOf(1,2)!=-1)Array.prototype.indexOf=function indexOf(sought){var self=splitString&&_toString(this)=="[object String]"?this.split(""):toObject(this),length=self.length>>>0;if(!length)return-1;var i=0;if(arguments.length>1)i=toInteger(arguments[1]);i=i>=0?i:Math.max(0,length+i);for(;i<length;i++)if(i in self&&self[i]===sought)return i;return-1};if(!Array.prototype.lastIndexOf||[0,1].lastIndexOf(0,-3)!=-1)Array.prototype.lastIndexOf=
function lastIndexOf(sought){var self=splitString&&_toString(this)=="[object String]"?this.split(""):toObject(this),length=self.length>>>0;if(!length)return-1;var i=length-1;if(arguments.length>1)i=Math.min(i,toInteger(arguments[1]));i=i>=0?i:length-Math.abs(i);for(;i>=0;i--)if(i in self&&sought===self[i])return i;return-1};if(!Object.keys){var hasDontEnumBug=true,dontEnums=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],dontEnumsLength=
dontEnums.length;for(var key in{"toString":null})hasDontEnumBug=false;Object.keys=function keys(object){if(typeof object!="object"&&typeof object!="function"||object===null)throw new TypeError("Object.keys called on a non-object");var keys=[];for(var name in object)if(owns(object,name))keys.push(name);if(hasDontEnumBug)for(var i=0,ii=dontEnumsLength;i<ii;i++){var dontEnum=dontEnums[i];if(owns(object,dontEnum))keys.push(dontEnum)}return keys}}var negativeDate=-621987552E5,negativeYearString="-000001";
if(!Date.prototype.toISOString||(new Date(negativeDate)).toISOString().indexOf(negativeYearString)===-1)Date.prototype.toISOString=function toISOString(){var result,length,value,year,month;if(!isFinite(this))throw new RangeError("Date.prototype.toISOString called on non-finite value.");year=this.getUTCFullYear();month=this.getUTCMonth();year+=Math.floor(month/12);month=(month%12+12)%12;result=[month+1,this.getUTCDate(),this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds()];year=(year<0?"-":
year>9999?"+":"")+("00000"+Math.abs(year)).slice(0<=year&&year<=9999?-4:-6);length=result.length;while(length--){value=result[length];if(value<10)result[length]="0"+value}return year+"-"+result.slice(0,2).join("-")+"T"+result.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"};var dateToJSONIsSupported=false;try{dateToJSONIsSupported=Date.prototype.toJSON&&(new Date(NaN)).toJSON()===null&&(new Date(negativeDate)).toJSON().indexOf(negativeYearString)!==-1&&Date.prototype.toJSON.call({toISOString:function(){return true}})}catch(e){}if(!dateToJSONIsSupported)Date.prototype.toJSON=
function toJSON(key){var o=Object(this),tv=toPrimitive(o),toISO;if(typeof tv==="number"&&!isFinite(tv))return null;toISO=o.toISOString;if(typeof toISO!="function")throw new TypeError("toISOString property is not callable");return toISO.call(o)};if(!Date.parse||"Date.parse is buggy")Date=function(NativeDate){function Date(Y,M,D,h,m,s,ms){var length=arguments.length;if(this instanceof NativeDate){var date=length==1&&String(Y)===Y?new NativeDate(Date.parse(Y)):length>=7?new NativeDate(Y,M,D,h,m,s,ms):
length>=6?new NativeDate(Y,M,D,h,m,s):length>=5?new NativeDate(Y,M,D,h,m):length>=4?new NativeDate(Y,M,D,h):length>=3?new NativeDate(Y,M,D):length>=2?new NativeDate(Y,M):length>=1?new NativeDate(Y):new NativeDate;date.constructor=Date;return date}return NativeDate.apply(this,arguments)}var isoDateExpression=new RegExp("^"+"(\\d{4}|[+-]\\d{6})"+"(?:-(\\d{2})"+"(?:-(\\d{2})"+"(?:"+"T(\\d{2})"+":(\\d{2})"+"(?:"+":(\\d{2})"+"(?:\\.(\\d{3}))?"+")?"+"("+"Z|"+"(?:"+"([-+])"+"(\\d{2})"+":(\\d{2})"+")"+")?)?)?)?"+
"$");var months=[0,31,59,90,120,151,181,212,243,273,304,334,365];function dayFromMonth(year,month){var t=month>1?1:0;return months[month]+Math.floor((year-1969+t)/4)-Math.floor((year-1901+t)/100)+Math.floor((year-1601+t)/400)+365*(year-1970)}for(var key in NativeDate)Date[key]=NativeDate[key];Date.now=NativeDate.now;Date.UTC=NativeDate.UTC;Date.prototype=NativeDate.prototype;Date.prototype.constructor=Date;Date.parse=function parse(string){var match=isoDateExpression.exec(string);if(match){var year=
Number(match[1]),month=Number(match[2]||1)-1,day=Number(match[3]||1)-1,hour=Number(match[4]||0),minute=Number(match[5]||0),second=Number(match[6]||0),millisecond=Number(match[7]||0),offset=!match[4]||match[8]?0:Number(new NativeDate(1970,0)),signOffset=match[9]==="-"?1:-1,hourOffset=Number(match[10]||0),minuteOffset=Number(match[11]||0),result;if(hour<(minute>0||second>0||millisecond>0?24:25)&&minute<60&&second<60&&millisecond<1E3&&month>-1&&month<12&&hourOffset<24&&minuteOffset<60&&day>-1&&day<dayFromMonth(year,
month+1)-dayFromMonth(year,month)){result=((dayFromMonth(year,month)+day)*24+hour+hourOffset*signOffset)*60;result=((result+minute+minuteOffset*signOffset)*60+second)*1E3+millisecond+offset;if(-864E13<=result&&result<=864E13)return result}return NaN}return NativeDate.parse.apply(this,arguments)};return Date}(Date);if(!Date.now)Date.now=function now(){return(new Date).getTime()};if("0".split(void 0,0).length){var string_split=String.prototype.split;String.prototype.split=function(separator,limit){if(separator===
void 0&&limit===0)return[];return string_split.apply(this,arguments)}}if("".substr&&"0b".substr(-1)!=="b"){var string_substr=String.prototype.substr;String.prototype.substr=function(start,length){return string_substr.call(this,start<0?(start=this.length+start)<0?0:start:start,length)}}var ws="\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003"+"\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028"+"\u2029\ufeff";if(!String.prototype.trim||ws.trim()){ws="["+ws+"]";var trimBeginRegexp=
new RegExp("^"+ws+ws+"*"),trimEndRegexp=new RegExp(ws+ws+"*$");String.prototype.trim=function trim(){if(this===undefined||this===null)throw new TypeError("can't convert "+this+" to object");return String(this).replace(trimBeginRegexp,"").replace(trimEndRegexp,"")}}function toInteger(n){n=+n;if(n!==n)n=0;else if(n!==0&&n!==1/0&&n!==-(1/0))n=(n>0||-1)*Math.floor(Math.abs(n));return n}function isPrimitive(input){var type=typeof input;return input===null||type==="undefined"||type==="boolean"||type===
"number"||type==="string"}function toPrimitive(input){var val,valueOf,toString;if(isPrimitive(input))return input;valueOf=input.valueOf;if(typeof valueOf==="function"){val=valueOf.call(input);if(isPrimitive(val))return val}toString=input.toString;if(typeof toString==="function"){val=toString.call(input);if(isPrimitive(val))return val}throw new TypeError;}var toObject=function(o){if(o==null)throw new TypeError("can't convert "+o+" to object");return Object(o)}});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,6 @@
/**
* Backbone localStorage Adapter
* Version 1.1.4
*
* https://github.com/jeromegn/Backbone.localStorage
*/(function(a,b){typeof exports=="object"?module.exports=b(require("underscore"),require("backbone")):typeof define=="function"&&define.amd?define(["underscore","backbone"],function(c,d){return b(c||a._,d||a.Backbone)}):b(_,Backbone)})(this,function(a,b){function c(){return((1+Math.random())*65536|0).toString(16).substring(1)}function d(){return c()+c()+"-"+c()+"-"+c()+"-"+c()+"-"+c()+c()+c()}return b.LocalStorage=window.Store=function(a){if(!this.localStorage)throw"Backbone.localStorage: Environment does not support localStorage.";this.name=a;var b=this.localStorage().getItem(this.name);this.records=b&&b.split(",")||[]},a.extend(b.LocalStorage.prototype,{save:function(){this.localStorage().setItem(this.name,this.records.join(","))},create:function(a){return a.id||(a.id=d(),a.set(a.idAttribute,a.id)),this.localStorage().setItem(this.name+"-"+a.id,JSON.stringify(a)),this.records.push(a.id.toString()),this.save(),this.find(a)},update:function(b){return this.localStorage().setItem(this.name+"-"+b.id,JSON.stringify(b)),a.include(this.records,b.id.toString())||this.records.push(b.id.toString()),this.save(),this.find(b)},find:function(a){return this.jsonData(this.localStorage().getItem(this.name+"-"+a.id))},findAll:function(){return(a.chain||a)(this.records).map(function(a){return this.jsonData(this.localStorage().getItem(this.name+"-"+a))},this).compact().value()},destroy:function(b){return b.isNew()?!1:(this.localStorage().removeItem(this.name+"-"+b.id),this.records=a.reject(this.records,function(a){return a===b.id.toString()}),this.save(),b)},localStorage:function(){return localStorage},jsonData:function(a){return a&&JSON.parse(a)},_clear:function(){var b=this.localStorage(),c=new RegExp("^"+this.name+"-");b.removeItem(this.name),(a.chain||a)(b).keys().filter(function(a){return c.test(a)}).each(function(a){b.removeItem(a)})},_storageSize:function(){return this.localStorage().length}}),b.LocalStorage.sync=window.Store.sync=b.localSync=function(a,c,d){var e=c.localStorage||c.collection.localStorage,f,g,h=b.$.Deferred&&b.$.Deferred();try{switch(a){case"read":f=c.id!=undefined?e.find(c):e.findAll();break;case"create":f=e.create(c);break;case"update":f=e.update(c);break;case"delete":f=e.destroy(c)}}catch(i){i.code===DOMException.QUOTA_EXCEEDED_ERR&&e._storageSize()===0?g="Private browsing is unsupported":g=i.message}return f?(d&&d.success&&(b.VERSION==="0.9.10"?d.success(c,f,d):d.success(f)),h&&h.resolve(f)):(g=g?g:"Record Not Found",d&&d.error&&(b.VERSION==="0.9.10"?d.error(c,g,d):d.error(g)),h&&h.reject(g)),d&&d.complete&&d.complete(f),h&&h.promise()},b.ajaxSync=b.sync,b.getSyncMethod=function(a){return a.localStorage||a.collection&&a.collection.localStorage?b.localSync:b.ajaxSync},b.sync=function(a,c,d){return b.getSyncMethod(c).apply(this,[a,c,d])},b.LocalStorage});

View File

@@ -0,0 +1,39 @@
/*!
Lo-Dash 0.8.2 lodash.com/license
Underscore.js 1.4.2 underscorejs.org/LICENSE
*/
;(function(e,t){function s(e){if(e&&e.__wrapped__)return e;if(!(this instanceof s))return new s(e);this.__wrapped__=e}function o(e,t,n){t||(t=0);var r=e.length,i=r-t>=(n||H),s=i?{}:e;if(i)for(n=t-1;++n<r;){var o=e[n]+"";(Z.call(s,o)?s[o]:s[o]=[]).push(e[n])}return function(e){if(i){var n=e+"";return Z.call(s,n)&&-1<T(s[n],e)}return-1<T(s,e,t)}}function u(e,n){var r=e.b,i=n.b,e=e.a,n=n.a;if(e!==n){if(e>n||e===t)return 1;if(e<n||n===t)return-1}return r<i?-1:1}function a(e,t,n){function r(){var u=arguments
,a=s?this:t;return i||(e=t[o]),n.length&&(u=u.length?n.concat(nt.call(u)):n),this instanceof r?(p.prototype=e.prototype,a=new p,(u=e.apply(a,u))&&Ht[typeof u]?u:a):e.apply(a,u)}var i=m(e),s=!n,o=e;return s&&(n=t),r}function f(e,n){return e?"function"!=typeof e?function(t){return t[e]}:n!==t?function(t,r,i){return e.call(n,t,r,i)}:e:A}function l(){for(var e={e:"",g:Et,i:"",j:Mt,m:Tt,n:kt,o:J,p:"",q:n,r:_t,c:{d:""},l:{d:""}},t,i=-1;t=arguments[++i];)for(var s in t){var o=t[s];/d|h/.test(s)?("string"==typeof
o&&(o={b:o,k:o}),e.c[s]=o.b,e.l[s]=o.k):e[s]=o}t=e.a;if("d"!=(e.f=/^[^,]+/.exec(t)[0])||!e.c.h)e.c=r;i="",e.r&&(i+="'use strict';"),i+="var i,A,j="+e.f+",t="+(e.i||e.f)+";if(!"+e.f+")return t;"+e.p+";",e.c&&(i+="var k=j.length;i=-1;",e.l&&(i+="if(k===+k){"),e.n&&(i+="if(y.call(j)==w){j=j.split('')}"),i+=e.c.d+";while(++i<k){A=j[i];"+e.c.h+"}",e.l&&(i+="}"));if(e.l){e.c?i+="else {":e.m&&(i+="var k=j.length;i=-1;if(k&&O(j)){while(++i<k){A=j[i+=''];"+e.l.h+"}}else {"),e.g||(i+="var u=typeof j=='function'&&q.call(j,'prototype');"
);if(e.j&&e.q)i+="var n=-1,o=Y[typeof j]?l(j):[],k=o.length;"+e.l.d+";while(++n<k){i=o[n];",e.g||(i+="if(!(u&&i=='prototype')){"),i+="A=j[i];"+e.l.h+"",e.g||(i+="}");else{i+=e.l.d+";for(i in j){";if(!e.g||e.q)i+="if(",e.g||(i+="!(u&&i=='prototype')"),!e.g&&e.q&&(i+="&&"),e.q&&(i+="h.call(j,i)"),i+="){";i+="A=j[i];"+e.l.h+";";if(!e.g||e.q)i+="}"}i+="}";if(e.g){i+="var g=j.constructor;";for(s=0;7>s;s++)i+="i='"+e.o[s]+"';if(","constructor"==e.o[s]&&(i+="!(g&&g.prototype===j)&&"),i+="h.call(j,i)){A=j[i];"+
e.l.h+"}"}if(e.c||e.m)i+="}"}return i+=e.e+";return t",Function("D,E,F,I,e,f,J,h,M,O,Q,S,T,X,Y,l,q,v,w,y,z","var G=function("+t+"){"+i+"};return G")(Dt,_,L,u,Q,f,en,Z,T,v,$t,m,Jt,mt,Ht,ut,tt,nt,yt,rt)}function c(e){return"\\"+Bt[e]}function h(e){return Qt[e]}function p(){}function d(e){return Gt[e]}function v(e){return rt.call(e)==ct}function m(e){return"function"==typeof e}function g(e){var t=i;if(!e||"object"!=typeof e||v(e))return t;var n=e.constructor;return(!Lt||"function"==typeof e.toString||"string"!=typeof
(e+""))&&(!m(n)||n instanceof n)?xt?(en(e,function(e,n,r){return t=!Z.call(r,n),i}),t===i):(en(e,function(e,n){t=n}),t===i||Z.call(e,t)):t}function y(e,t,n,s,o){if(e==r)return e;n&&(t=i);if(n=Ht[typeof e]){var u=rt.call(e);if(!Pt[u]||Nt&&v(e))return e;var a=u==ht,n=a||(u==mt?Jt(e):n)}if(!n||!t)return n?a?nt.call(e):Zt({},e):e;n=e.constructor;switch(u){case pt:case dt:return new n(+e);case vt:case yt:return new n(e);case gt:return n(e.source,U.exec(e))}s||(s=[]),o||(o=[]);for(u=s.length;u--;)if(s[
u]==e)return o[u];var f=a?n(e.length):{};return s.push(e),o.push(f),(a?mn:tn)(e,function(e,n){f[n]=y(e,t,r,s,o)}),f}function b(e,t,s,o){if(e==r||t==r)return e===t;if(e===t)return 0!==e||1/e==1/t;if(Ht[typeof e]||Ht[typeof t])e=e.__wrapped__||e,t=t.__wrapped__||t;var u=rt.call(e);if(u!=rt.call(t))return i;switch(u){case pt:case dt:return+e==+t;case vt:return e!=+e?t!=+t:0==e?1/e==1/t:e==+t;case gt:case yt:return e==t+""}var a=Dt[u];if(Nt&&!a&&(a=v(e))&&!v(t)||!a&&(u!=mt||Lt&&("function"!=typeof e.
toString&&"string"==typeof (e+"")||"function"!=typeof t.toString&&"string"==typeof (t+""))))return i;s||(s=[]),o||(o=[]);for(u=s.length;u--;)if(s[u]==e)return o[u]==t;var u=-1,f=n,l=0;s.push(e),o.push(t);if(a){l=e.length;if(f=l==t.length)for(;l--&&(f=b(e[l],t[l],s,o)););return f}a=e.constructor,f=t.constructor;if(a!=f&&(!m(a)||!(a instanceof a&&m(f)&&f instanceof f)))return i;for(var c in e)if(Z.call(e,c)&&(l++,!Z.call(t,c)||!b(e[c],t[c],s,o)))return i;for(c in t)if(Z.call(t,c)&&!(l--))return i;if(
Et)for(;7>++u;)if(c=J[u],Z.call(e,c)&&(!Z.call(t,c)||!b(e[c],t[c],s,o)))return i;return n}function w(e,t,n){var r=-Infinity,i=-1,s=e?e.length:0,o=r;if(t||s!==+s)t=f(t,n),mn(e,function(e,n,i){n=t(e,n,i),n>r&&(r=n,o=e)});else for(;++i<s;)e[i]>o&&(o=e[i]);return o}function E(e,t,n,r){var s=e,o=e?e.length:0,u=3>arguments.length;if(o!==+o)var a=sn(e),o=a.length;else kt&&rt.call(e)==yt&&(s=e.split(""));return mn(e,function(e,f,l){f=a?a[--o]:--o,n=u?(u=i,s[f]):t.call(r,n,s[f],f,l)}),n}function S(e,t,n){
if(e)return t==r||n?e[0]:nt.call(e,0,t)}function x(e,t){for(var n=-1,r=e?e.length:0,i=[];++n<r;){var s=e[n];$t(s)?et.apply(i,t?s:x(s)):i.push(s)}return i}function T(e,t,n){var r=-1,i=e?e.length:0;if("number"==typeof n)r=(0>n?at(0,i+n):n||0)-1;else if(n)return r=C(e,t),e[r]===t?r:-1;for(;++r<i;)if(e[r]===t)return r;return-1}function N(e,t,n){return e?nt.call(e,t==r||n?1:t):[]}function C(e,t,n,r){var i=0,s=e?e.length:i;if(n){n=f(n,r);for(t=n(t);i<s;)r=i+s>>>1,n(e[r])<t?i=r+1:s=r}else for(;i<s;)r=i+
s>>>1,e[r]<t?i=r+1:s=r;return i}function k(e,t,n,r){var s=-1,o=e?e.length:0,u=[],a=[];"function"==typeof t&&(r=n,n=t,t=i);for(n=f(n,r);++s<o;)if(r=n(e[s],s,e),t?!s||a[a.length-1]!==r:0>T(a,r))a.push(r),u.push(e[s]);return u}function L(e,t){return Ot||it&&2<arguments.length?it.call.apply(it,arguments):a(e,t,nt.call(arguments,2))}function A(e){return e}function O(e){mn(nn(e),function(t){var r=s[t]=e[t];s.prototype[t]=function(){var e=[this.__wrapped__];return arguments.length&&et.apply(e,arguments)
,e=r.apply(s,e),this.__chain__&&(e=new s(e),e.__chain__=n),e}})}var n=!0,r=null,i=!1,M="object"==typeof exports&&exports&&("object"==typeof global&&global&&global==global.global&&(e=global),exports),_=Array.prototype,D=Object.prototype,P=0,H=30,B=e._,j=/[-?+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/,F=/&(?:amp|lt|gt|quot|#x27);/g,I=/\b__p\+='';/g,q=/\b(__p\+=)''\+/g,R=/(__e\(.*?\)|\b__t\))\+'';/g,U=/\w*$/,z=/(?:__e|__t=)\(\s*(?![\d\s"']|this\.)/g,W=RegExp("^"+(D.valueOf+""
).replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),X=/($^)/,V=/[&<>"']/g,$=/['\n\r\t\u2028\u2029\\]/g,J="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),K=Math.ceil,Q=_.concat,G=Math.floor,Y=W.test(Y=Object.getPrototypeOf)&&Y,Z=D.hasOwnProperty,et=_.push,tt=D.propertyIsEnumerable,nt=_.slice,rt=D.toString,it=W.test(it=nt.bind)&&it,st=W.test(st=Array.isArray)&&st,ot=e.isFinite,ut=W.test(ut=Object.keys)&&ut
,at=Math.max,ft=Math.min,lt=Math.random,ct="[object Arguments]",ht="[object Array]",pt="[object Boolean]",dt="[object Date]",vt="[object Number]",mt="[object Object]",gt="[object RegExp]",yt="[object String]",bt=e.clearTimeout,wt=e.setTimeout,Et,St,xt,Tt=n;(function(){function e(){this.x=1}var t={0:1,length:1},n=[];e.prototype={valueOf:1,y:1};for(var r in new e)n.push(r);for(r in arguments)Tt=!r;Et=4>(n+"").length,xt="x"!=n[0],St=(n.splice.call(t,0,1),t[0])})(1);var Nt=!v(arguments),Ct="x"!=nt.call("x"
)[0],kt="xx"!="x"[0]+Object("x")[0];try{var Lt=("[object Object]",rt.call(e.document||0)==mt)}catch(At){}var Ot=it&&/\n|Opera/.test(it+rt.call(e.opera)),Mt=ut&&/^.+$|true/.test(ut+!!e.attachEvent),_t=!Ot,Dt={};Dt[pt]=Dt[dt]=Dt["[object Function]"]=Dt[vt]=Dt[mt]=Dt[gt]=i,Dt[ct]=Dt[ht]=Dt[yt]=n;var Pt={};Pt[ct]=Pt["[object Function]"]=i,Pt[ht]=Pt[pt]=Pt[dt]=Pt[vt]=Pt[mt]=Pt[gt]=Pt[yt]=n;var Ht={"boolean":i,"function":n,object:n,number:i,string:i,"undefined":i,unknown:n},Bt={"\\":"\\","'":"'","\n":"n"
,"\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};s.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""};var jt={a:"d,c,x",p:"c=f(c,x)",h:"if(c(A,i,d)===false)return t"},Ft={i:"{}",p:"c=f(c,x)",h:"var p=c(A,i,d);(h.call(t,p)?t[p]++:t[p]=1)"},It={i:"true",h:"if(!c(A,i,d))return!t"},qt={q:i,r:i,a:"m",p:"for(var a=1,b=arguments.length;a<b;a++){if(j=arguments[a]){",h:"t[i]=A",e:"}}"},Rt={i:"[]",h:"c(A,i,d)&&t.push(A)"},Ut={p:"c=f(c,x)"}
,zt={h:{k:jt.h}},Wt={i:"d||[]",d:{b:"t=Array(k)",k:"t="+(Mt?"Array(k)":"[]")},h:{b:"t[i]=c(A,i,d)",k:"t"+(Mt?"[n]=":".push")+"(c(A,i,d))"}},Xt={q:i,a:"m,c,x",i:"{}",p:"var R=typeof c=='function';if(R)c=f(c,x);else var s=e.apply(E,arguments)",h:"if(R?!c(A,i,m):M(s,i)<0)t[i]=A"},Vt=l({a:"m",i:"{}",h:"t[A]=i"});Nt&&(v=function(e){return e?Z.call(e,"callee"):i});var $t=st||function(e){return rt.call(e)==ht};m(/x/)&&(m=function(e){return"[object Function]"==rt.call(e)});var Jt=Y?function(e){if(!e||"object"!=typeof
e)return i;var t=e.valueOf,n="function"==typeof t&&(n=Y(t))&&Y(n);return n?e==n||Y(e)==n&&!v(e):g(e)}:g,Kt=l({a:"m",i:"[]",h:"t.push(i)"}),Qt={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;"},Gt=Vt(Qt),Yt=l(qt,{h:"if(t[i]==null)"+qt.h}),Zt=l(qt),en=l(jt,Ut,zt,{q:i}),tn=l(jt,Ut,zt),nn=l({q:i,a:"m",i:"[]",h:"S(A)&&t.push(i)",e:"t.sort()"}),rn=l({a:"A",i:"true",p:"var H=y.call(A),k=A.length;if(D[H]"+(Nt?"||O(A)":"")+"||(H==X&&k===+k&&S(A.splice)))return!k",h:{k:"return false"}}),sn=ut?function(
e){var t=typeof e;return"function"==t&&tt.call(e,"prototype")?Kt(e):e&&Ht[t]?ut(e):[]}:Kt,on=l(qt,{a:"m,dd,N",p:"var P,C=arguments,a=0;if(N==I){var b=2,ee=C[3],ff=C[4]}else var b=C.length,ee=[],ff=[];while(++a<b){if(j=C[a]){",h:"if((dd=A)&&((P=Q(dd))||T(dd))){var K=false,gg=ee.length;while(gg--)if(K=ee[gg]==dd)break;if(K){t[i]=ff[gg]}else {ee.push(dd);ff.push(A=(A=t[i],P)?(Q(A)?A:[]):(T(A)?A:{}));t[i]=G(A,dd,I,ee,ff)}}else if(dd!=null)t[i]=dd"}),un=l(Xt),an=l({a:"m",i:"[]",h:"t"+(Mt?"[n]=":".push"
)+"([i,A])"}),fn=l(Xt,{p:"if(typeof c!='function'){var i=0,s=e.apply(E,arguments),k=s.length;while(++i<k){var p=s[i];if(p in m)t[p]=m[p]}}else {c=f(c,x)",h:"if(c(A,i,m))t[i]=A",e:"}"}),ln=l({a:"m",i:"[]",h:"t.push(A)"}),cn=l({a:"d,hh",i:"false",n:i,d:{b:"if(y.call(d)==w)return d.indexOf(hh)>-1"},h:"if(A===hh)return true"}),hn=l(jt,Ft),pn=l(jt,It),dn=l(jt,Rt),vn=l(jt,Ut,{i:"z",h:"if(c(A,i,d))return A"}),mn=l(jt,Ut),gn=l(jt,Ft,{h:"var p=c(A,i,d);(h.call(t,p)?t[p]:t[p]=[]).push(A)"}),yn=l(Wt,{a:"d,U"
,p:"var C=v.call(arguments,2),R=typeof U=='function'",h:{b:"t[i]=(R?U:A[U]).apply(A,C)",k:"t"+(Mt?"[n]=":".push")+"((R?U:A[U]).apply(A,C))"}}),bn=l(jt,Wt),wn=l(Wt,{a:"d,bb",h:{b:"t[i]=A[bb]",k:"t"+(Mt?"[n]=":".push")+"(A[bb])"}}),En=l({a:"d,c,B,x",i:"B",p:"var V=arguments.length<3;c=f(c,x)",d:{b:"if(V)t=j[++i]"},h:{b:"t=c(t,A,i,d)",k:"t=V?(V=false,A):c(t,A,i,d)"}}),Sn=l(jt,Rt,{h:"!"+Rt.h}),xn=l(jt,It,{i:"false",h:It.h.replace("!","")}),Tn=l(jt,Ft,Wt,{h:{b:"t[i]={a:c(A,i,d),b:i,c:A}",k:"t"+(Mt?"[n]="
:".push")+"({a:c(A,i,d),b:i,c:A})"},e:"t.sort(I);k=t.length;while(k--)t[k]=t[k].c"}),Nn=l(Rt,{a:"d,aa",p:"var s=[];J(aa,function(A,p){s.push(p)});var cc=s.length",h:"for(var Z=true,r=0;r<cc;r++){var p=s[r];if(!(Z=A[p]===aa[p]))break}Z&&t.push(A)"}),Cn=l({q:i,r:i,a:"m",p:"var L=arguments,i=0,k=L.length;if(k>1){while(++i<k)t[L[i]]=F(t[L[i]],t);return t}",h:"if(S(A))t[i]=F(A,t)"});s.VERSION="0.8.2",s.after=function(e,t){return 1>e?t():function(){if(1>--e)return t.apply(this,arguments)}},s.bind=L,s.bindAll=
Cn,s.chain=function(e){return e=new s(e),e.__chain__=n,e},s.clone=y,s.compact=function(e){for(var t=-1,n=e?e.length:0,r=[];++t<n;){var i=e[t];i&&r.push(i)}return r},s.compose=function(){var e=arguments;return function(){for(var t=arguments,n=e.length;n--;)t=[e[n].apply(this,t)];return t[0]}},s.contains=cn,s.countBy=hn,s.debounce=function(e,t,n){function i(){a=r,n||(o=e.apply(u,s))}var s,o,u,a;return function(){var r=n&&!a;return s=arguments,u=this,bt(a),a=wt(i,t),r&&(o=e.apply(u,s)),o}},s.defaults=
Yt,s.defer=function(e){var n=nt.call(arguments,1);return wt(function(){return e.apply(t,n)},1)},s.delay=function(e,n){var r=nt.call(arguments,2);return wt(function(){return e.apply(t,r)},n)},s.difference=function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length,i=Q.apply(_,arguments),i=o(i,r);++n<r;){var s=e[n];i(s)||t.push(s)}return t},s.escape=function(e){return e==r?"":(e+"").replace(V,h)},s.every=pn,s.extend=Zt,s.filter=dn,s.find=vn,s.first=S,s.flatten=x,s.forEach=mn,s.forIn=en,s.forOwn=tn,
s.functions=nn,s.groupBy=gn,s.has=function(e,t){return e?Z.call(e,t):i},s.identity=A,s.indexOf=T,s.initial=function(e,t,n){return e?nt.call(e,0,-(t==r||n?1:t)):[]},s.intersection=function(e){var t=arguments.length,n=[],r=-1,i=e?e.length:0,s=[];e:for(;++r<i;){var u=e[r];if(0>T(s,u)){for(var a=1;a<t;a++)if(!(n[a]||(n[a]=o(arguments[a])))(u))continue e;s.push(u)}}return s},s.invert=Vt,s.invoke=yn,s.isArguments=v,s.isArray=$t,s.isBoolean=function(e){return e===n||e===i||rt.call(e)==pt},s.isDate=function(
e){return rt.call(e)==dt},s.isElement=function(e){return e?1===e.nodeType:i},s.isEmpty=rn,s.isEqual=b,s.isFinite=function(e){return ot(e)&&rt.call(e)==vt},s.isFunction=m,s.isNaN=function(e){return rt.call(e)==vt&&e!=+e},s.isNull=function(e){return e===r},s.isNumber=function(e){return rt.call(e)==vt},s.isObject=function(e){return e?Ht[typeof e]:i},s.isPlainObject=Jt,s.isRegExp=function(e){return rt.call(e)==gt},s.isString=function(e){return rt.call(e)==yt},s.isUndefined=function(e){return e===t},s
.keys=sn,s.last=function(e,t,n){if(e){var i=e.length;return t==r||n?e[i-1]:nt.call(e,-t||i)}},s.lastIndexOf=function(e,t,n){var r=e?e.length:0;for("number"==typeof n&&(r=(0>n?at(0,r+n):ft(n,r-1))+1);r--;)if(e[r]===t)return r;return-1},s.lateBind=function(e,t){return a(t,e,nt.call(arguments,2))},s.map=bn,s.max=w,s.memoize=function(e,t){var n={};return function(){var r=t?t.apply(this,arguments):arguments[0];return Z.call(n,r)?n[r]:n[r]=e.apply(this,arguments)}},s.merge=on,s.min=function(e,t,n){var r=
Infinity,i=-1,s=e?e.length:0,o=r;if(t||s!==+s)t=f(t,n),mn(e,function(e,n,i){n=t(e,n,i),n<r&&(r=n,o=e)});else for(;++i<s;)e[i]<o&&(o=e[i]);return o},s.mixin=O,s.noConflict=function(){return e._=B,this},s.object=function(e,t){for(var n=-1,r=e?e.length:0,i={};++n<r;){var s=e[n];t?i[s]=t[n]:i[s[0]]=s[1]}return i},s.omit=un,s.once=function(e){var t,s=i;return function(){return s?t:(s=n,t=e.apply(this,arguments),e=r,t)}},s.pairs=an,s.partial=function(e){return a(e,nt.call(arguments,1))},s.pick=fn,s.pluck=
wn,s.random=function(e,t){return e==r&&t==r&&(t=1),e=+e||0,t==r&&(t=e,e=0),e+G(lt()*((+t||0)-e+1))},s.range=function(e,t,n){e=+e||0,n=+n||1,t==r&&(t=e,e=0);for(var i=-1,t=at(0,K((t-e)/n)),s=Array(t);++i<t;)s[i]=e,e+=n;return s},s.reduce=En,s.reduceRight=E,s.reject=Sn,s.rest=N,s.result=function(e,t){var n=e?e[t]:r;return m(n)?e[t]():n},s.shuffle=function(e){var t=-1,n=Array(e?e.length:0);return mn(e,function(e){var r=G(lt()*(++t+1));n[t]=n[r],n[r]=e}),n},s.size=function(e){var t=e?e.length:0;return t===+
t?t:sn(e).length},s.some=xn,s.sortBy=Tn,s.sortedIndex=C,s.tap=function(e,t){return t(e),e},s.template=function(e,t,n){e||(e=""),n||(n={});var r,i,o=0,u=s.templateSettings,a="__p += '",f=n.variable||u.variable,l=f;e.replace(RegExp((n.escape||u.escape||X).source+"|"+(n.interpolate||u.interpolate||X).source+"|"+(n.evaluate||u.evaluate||X).source+"|$","g"),function(t,n,i,s,u){a+=e.slice(o,u).replace($,c),a+=n?"'+__e("+n+")+'":s?"';"+s+";__p+='":i?"'+((__t=("+i+"))==null?'':__t)+'":"",r||(r=s||j.test(
n||i)),o=u+t.length}),a+="';",l||(f="obj",r?a="with("+f+"){"+a+"}":(n=RegExp("(\\(\\s*)"+f+"\\."+f+"\\b","g"),a=a.replace(z,"$&"+f+".").replace(n,"$1__d"))),a=(r?a.replace(I,""):a).replace(q,"$1").replace(R,"$1;"),a="function("+f+"){"+(l?"":f+"||("+f+"={});")+"var __t,__p='',__e=_.escape"+(r?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":(l?"":",__d="+f+"."+f+"||"+f)+";")+a+"return __p}";try{i=Function("_","return "+a)(s)}catch(h){throw h.source=a,h}return t?i(t):(i.source=
a,i)},s.throttle=function(e,t){function n(){a=new Date,u=r,s=e.apply(o,i)}var i,s,o,u,a=0;return function(){var r=new Date,f=t-(r-a);return i=arguments,o=this,0>=f?(bt(u),a=r,s=e.apply(o,i)):u||(u=wt(n,f)),s}},s.times=function(e,t,n){for(var e=+e||0,r=-1,i=Array(e);++r<e;)i[r]=t.call(n,r);return i},s.toArray=function(e){if(!e)return[];var t=e.length;return t===+t?(Ct?rt.call(e)==yt:"string"==typeof e)?e.split(""):nt.call(e):ln(e)},s.unescape=function(e){return e==r?"":(e+"").replace(F,d)},s.union=
function(){for(var e=-1,t=Q.apply(_,arguments),n=t.length,r=[];++e<n;){var i=t[e];0>T(r,i)&&r.push(i)}return r},s.uniq=k,s.uniqueId=function(e){var t=P++;return e?e+t:t},s.values=ln,s.where=Nn,s.without=function(e){for(var t=-1,n=e?e.length:0,r=o(arguments,1,20),i=[];++t<n;){var s=e[t];r(s)||i.push(s)}return i},s.wrap=function(e,t){return function(){var n=[e];return arguments.length&&et.apply(n,arguments),t.apply(this,n)}},s.zip=function(e){for(var t=-1,n=e?w(wn(arguments,"length")):0,r=Array(n);++
t<n;)r[t]=wn(arguments,t);return r},s.all=pn,s.any=xn,s.collect=bn,s.detect=vn,s.drop=N,s.each=mn,s.foldl=En,s.foldr=E,s.head=S,s.include=cn,s.inject=En,s.methods=nn,s.select=dn,s.tail=N,s.take=S,s.unique=k,O(s),s.prototype.chain=function(){return this.__chain__=n,this},s.prototype.value=function(){return this.__wrapped__},mn("pop push reverse shift sort splice unshift".split(" "),function(e){var t=_[e];s.prototype[e]=function(){var e=this.__wrapped__;return t.apply(e,arguments),St&&e.length===0&&delete
e[0],this.__chain__&&(e=new s(e),e.__chain__=n),e}}),mn(["concat","join","slice"],function(e){var t=_[e];s.prototype[e]=function(){var e=t.apply(this.__wrapped__,arguments);return this.__chain__&&(e=new s(e),e.__chain__=n),e}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(e._=s,define(function(){return s})):M?"object"==typeof module&&module&&module.exports==M?(module.exports=s)._=s:M._=s:e._=s})(this);

View File

@@ -0,0 +1,11 @@
# TodoMVC-director
This is the exact copy of the React-powered [TodoMVC](http://todomvc.com/labs/architecture-examples/react/). To test it, use [bower](http://bower.io) to fetch the dependencies:
`bower install`
Then fire up a server here:
`python -m SimpleHTTPServer`
And go visit `localhost:8000`.

View File

@@ -0,0 +1,9 @@
{
"name": "todomvc-react",
"version": "0.0.0",
"dependencies": {
"todomvc-common": "~0.1.7",
"react": "~0.4.0",
"director": "~1.2.0"
}
}

View File

@@ -0,0 +1,24 @@
<!doctype html>
<html lang="en" data-framework="react">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>React • TodoMVC</title>
<link rel="stylesheet" href="bower_components/todomvc-common/base.css">
</head>
<body>
<section id="todoapp"></section>
<footer id="info"></footer>
<div id="benchmark"></div>
<script src="bower_components/todomvc-common/base.js"></script>
<script src="bower_components/react/react.js"></script>
<script src="bower_components/react/JSXTransformer.js"></script>
<script src="bower_components/director/build/director.min.js"></script>
<script type="text/jsx" src="js/utils.jsx"></script>
<script type="text/jsx" src="js/todoItem.jsx"></script>
<script type="text/jsx" src="js/footer.jsx"></script>
<script type="text/jsx" src="js/app.jsx"></script>
</body>
</html>

View File

@@ -0,0 +1,207 @@
/**
* @jsx React.DOM
*/
/*jshint quotmark:false */
/*jshint white:false */
/*jshint trailing:false */
/*jshint newcap:false */
/*global Utils, ALL_TODOS, ACTIVE_TODOS, COMPLETED_TODOS,
TodoItem, TodoFooter, React, Router*/
(function (window, React) {
'use strict';
window.ALL_TODOS = 'all';
window.ACTIVE_TODOS = 'active';
window.COMPLETED_TODOS = 'completed';
var ENTER_KEY = 13;
var TodoApp = React.createClass({
getInitialState: function () {
var todos = Utils.store('react-todos');
return {
todos: todos,
nowShowing: ALL_TODOS,
editing: null
};
},
componentDidMount: function () {
var router = Router({
'/': this.setState.bind(this, {nowShowing: ALL_TODOS}),
'/active': this.setState.bind(this, {nowShowing: ACTIVE_TODOS}),
'/completed': this.setState.bind(this, {nowShowing: COMPLETED_TODOS})
});
router.init();
this.refs.newField.getDOMNode().focus();
},
handleNewTodoKeyDown: function (event) {
if (event.which !== ENTER_KEY) {
return;
}
var val = this.refs.newField.getDOMNode().value.trim();
var todos;
var newTodo;
if (val) {
todos = this.state.todos;
newTodo = {
id: Utils.uuid(),
title: val,
completed: false
};
this.setState({todos: todos.concat([newTodo])});
this.refs.newField.getDOMNode().value = '';
}
return false;
},
toggleAll: function (event) {
var checked = event.target.checked;
this.state.todos.forEach(function (todo) {
todo.completed = checked;
});
this.setState({todos: this.state.todos});
},
toggle: function (todo) {
todo.completed = !todo.completed;
this.setState({todos: this.state.todos});
},
destroy: function (todo) {
var newTodos = this.state.todos.filter(function (candidate) {
return candidate.id !== todo.id;
});
this.setState({todos: newTodos});
},
edit: function (todo, callback) {
// refer to todoItem.js `handleEdit` for the reasoning behind the
// callback
this.setState({editing: todo.id}, function () {
callback();
});
},
save: function (todo, text) {
todo.title = text;
this.setState({todos: this.state.todos, editing: null});
},
cancel: function () {
this.setState({editing: null});
},
clearCompleted: function () {
var newTodos = this.state.todos.filter(function (todo) {
return !todo.completed;
});
this.setState({todos: newTodos});
},
componentDidUpdate: function () {
Utils.store('react-todos', this.state.todos);
},
render: function () {
var footer = null;
var main = null;
var todoItems = {};
var activeTodoCount;
var completedCount;
var shownTodos = this.state.todos.filter(function (todo) {
switch (this.state.nowShowing) {
case ACTIVE_TODOS:
return !todo.completed;
case COMPLETED_TODOS:
return todo.completed;
default:
return true;
}
}.bind(this));
shownTodos.forEach(function (todo) {
todoItems[todo.id] = (
<TodoItem
todo={todo}
onToggle={this.toggle.bind(this, todo)}
onDestroy={this.destroy.bind(this, todo)}
onEdit={this.edit.bind(this, todo)}
editing={this.state.editing === todo.id}
onSave={this.save.bind(this, todo)}
onCancel={this.cancel}
/>
);
}.bind(this));
activeTodoCount = this.state.todos.filter(function (todo) {
return !todo.completed;
}).length;
completedCount = this.state.todos.length - activeTodoCount;
if (activeTodoCount || completedCount) {
footer =
<TodoFooter
count={activeTodoCount}
completedCount={completedCount}
nowShowing={this.state.nowShowing}
onClearCompleted={this.clearCompleted}
/>;
}
if (this.state.todos.length) {
main = (
<section id="main">
<input
id="toggle-all"
type="checkbox"
onChange={this.toggleAll}
checked={activeTodoCount === 0}
/>
<ul id="todo-list">
{todoItems}
</ul>
</section>
);
}
return (
<div>
<header id="header">
<h1>todos</h1>
<input
ref="newField"
id="new-todo"
placeholder="What needs to be done?"
onKeyDown={this.handleNewTodoKeyDown}
/>
</header>
{main}
{footer}
</div>
);
}
});
React.renderComponent(<TodoApp />, document.getElementById('todoapp'));
React.renderComponent(
<div>
<p>Double-click to edit a todo</p>
<p>Created by{' '}
<a href="http://github.com/petehunt/">petehunt</a>
</p>
<p>Part of{' '}<a href="http://todomvc.com">TodoMVC</a></p>
</div>,
document.getElementById('info'));
})(window, React);

View File

@@ -0,0 +1,58 @@
/**
* @jsx React.DOM
*/
/*jshint quotmark:false */
/*jshint white:false */
/*jshint trailing:false */
/*jshint newcap:false */
/*global React, ALL_TODOS, ACTIVE_TODOS, Utils, COMPLETED_TODOS */
(function (window) {
'use strict';
window.TodoFooter = React.createClass({
render: function () {
var activeTodoWord = Utils.pluralize(this.props.count, 'item');
var clearButton = null;
if (this.props.completedCount > 0) {
clearButton = (
<button
id="clear-completed"
onClick={this.props.onClearCompleted}>
{''}Clear completed ({this.props.completedCount}){''}
</button>
);
}
var show = {
ALL_TODOS: '',
ACTIVE_TODOS: '',
COMPLETED_TODOS: ''
};
show[this.props.nowShowing] = 'selected';
return (
<footer id="footer">
<span id="todo-count">
<strong>{this.props.count}</strong>
{' '}{activeTodoWord}{' '}left{''}
</span>
<ul id="filters">
<li>
<a href="#/" className={show[ALL_TODOS]}>All</a>
</li>
{' '}
<li>
<a href="#/active" className={show[ACTIVE_TODOS]}>Active</a>
</li>
{' '}
<li>
<a href="#/completed" className={show[COMPLETED_TODOS]}>Completed</a>
</li>
</ul>
{clearButton}
</footer>
);
}
});
})(window);

View File

@@ -0,0 +1,93 @@
/**
* @jsx React.DOM
*/
/*jshint quotmark: false */
/*jshint white: false */
/*jshint trailing: false */
/*jshint newcap: false */
/*global React, Utils */
(function (window) {
'use strict';
var ESCAPE_KEY = 27;
var ENTER_KEY = 13;
window.TodoItem = React.createClass({
handleSubmit: function () {
var val = this.state.editText.trim();
if (val) {
this.props.onSave(val);
this.setState({editText: val});
} else {
this.props.onDestroy();
}
return false;
},
handleEdit: function () {
// react optimizes renders by batching them. This means you can't call
// parent's `onEdit` (which in this case triggeres a re-render), and
// immediately manipulate the DOM as if the rendering's over. Put it as a
// callback. Refer to app.js' `edit` method
this.props.onEdit(function () {
var node = this.refs.editField.getDOMNode();
node.focus();
node.setSelectionRange(node.value.length, node.value.length);
}.bind(this));
},
handleKeyDown: function (event) {
if (event.keyCode === ESCAPE_KEY) {
this.setState({editText: this.props.todo.title});
this.props.onCancel();
} else if (event.keyCode === ENTER_KEY) {
this.handleSubmit();
} else {
this.setState({editText: event.target.value});
}
},
handleChange: function (event) {
this.setState({editText: event.target.value});
},
getInitialState: function () {
return {editText: this.props.todo.title};
},
componentWillReceiveProps: function (nextProps) {
if (nextProps.todo.title !== this.props.todo.title) {
this.setState(this.getInitialState());
}
},
render: function () {
return (
<li className={Utils.stringifyObjKeys({
completed: this.props.todo.completed,
editing: this.props.editing
})}>
<div className="view">
<input
className="toggle"
type="checkbox"
checked={this.props.todo.completed ? 'checked' : null}
onChange={this.props.onToggle}
/>
<label onDoubleClick={this.handleEdit}>
{this.props.todo.title}
</label>
<button className='destroy' onClick={this.props.onDestroy} />
</div>
<input
ref="editField"
className="edit"
value={this.state.editText}
onBlur={this.handleSubmit}
onChange={this.handleChange}
onKeyDown={this.handleKeyDown}
/>
</li>
);
}
});
})(window);

View File

@@ -0,0 +1,49 @@
(function (window) {
'use strict';
window.Utils = {
uuid: function () {
/*jshint bitwise:false */
var i, random;
var uuid = '';
for (i = 0; i < 32; i++) {
random = Math.random() * 16 | 0;
if (i === 8 || i === 12 || i === 16 || i === 20) {
uuid += '-';
}
uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random))
.toString(16);
}
return uuid;
},
pluralize: function (count, word) {
return count === 1 ? word : word + 's';
},
store: function (namespace, data) {
if (data) {
return localStorage.setItem(namespace, JSON.stringify(data));
}
var store = localStorage.getItem(namespace);
return (store && JSON.parse(store)) || [];
},
stringifyObjKeys: function (obj) {
var s = '';
var key;
for (key in obj) {
if (obj.hasOwnProperty(key) && obj[key]) {
s += key + ' ';
}
}
return s.trim();
}
};
})(window);

View File

@@ -2,7 +2,7 @@
<html>
<head>
<meta http-equiv='Content-type' content='text/html; charset=utf-8'>
<title>Example with Transitions</title>
<title>Basic Example with JSX</title>
<link rel="stylesheet" href="../shared/css/base.css" />
<link rel="stylesheet" href="transition.css" />
</head>
@@ -19,9 +19,19 @@
</p>
</div>
<h4>Example Details</h4>
<p>This is written with JSX and transformed in the browser.<p>
<ul>
<li>
This is built with
<a href="https://github.com/substack/node-browserify">browserify</a>.
</li>
<li>
This is written with JSX and transformed in the browser.
</li>
</ul>
<p>
Learn more about React at
</p>
<p>
Learn more at
<a href="http://facebook.github.io/react" target="_blank">facebook.github.io/react</a>.
</p>
<script src="../../build/react-with-addons.js"></script>
@@ -30,7 +40,7 @@
/**
* @jsx React.DOM
*/
var CSSTransitionGroup = React.addons.CSSTransitionGroup;
var TransitionGroup = React.addons.TransitionGroup;
var INTERVAL = 2000;
var AnimateDemo = React.createClass({
@@ -63,11 +73,11 @@
children.push(<div key={i} className="animateItem" style={style}>{i}</div>);
}
return (
<CSSTransitionGroup
<TransitionGroup
className="animateExample"
transitionName="example">
{children}
</CSSTransitionGroup>
</TransitionGroup>
);
}
});

View File

@@ -0,0 +1,54 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='Content-type' content='text/html; charset=utf-8'>
<title>Basic Example (WrapUp)</title>
<link rel="stylesheet" href="../shared/css/base.css" />
</head>
<body>
<h1>Basic Example (WrapUp)</h1>
<div id="container">
<p>
To install React, follow the instructions on
<a href="http://www.github.com/facebook/react/">GitHub</a>.
</p>
<p>
If you can see this, React is not working right.
Make sure to run <code>grunt</code>.
</p>
</div>
<h4>Example Details</h4>
<ul>
<li>
This is built with
<a href="https://github.com/mootools/wrapup">WrapUp</a>.
</li>
</ul>
<p>
</p>
<p>
Learn more at
<a href="http://facebook.github.io/react" target="_blank">facebook.github.io/react</a>.
</p>
<script src="../../build/react.js"></script>
<script>
var ExampleApplication = React.createClass({
render: function() {
var elapsed = Math.round(this.props.elapsed / 100);
var seconds = elapsed / 10 + (elapsed % 10 ? '' : '.0' );
var message =
'React has been successfully running for ' + seconds + ' seconds.';
return React.DOM.p(null, message);
}
});
var start = new Date().getTime();
setInterval(function() {
React.renderComponent(
ExampleApplication({elapsed: new Date().getTime() - start}),
document.getElementById('container')
);
}, 50);
</script>
</body>
</html>

View File

@@ -4,11 +4,8 @@
'use strict';
var envify = require('envify/custom');
var es3ify = require('es3ify');
var grunt = require('grunt');
var UglifyJS = require('uglify-js');
var uglifyify = require('uglifyify');
var _ = require('lodash');
var SIMPLE_TEMPLATE =
'/**\n\
@@ -19,7 +16,7 @@ var LICENSE_TEMPLATE =
'/**\n\
* @PACKAGE@ v@VERSION@\n\
*\n\
* Copyright 2013-2014 Facebook, Inc.\n\
* Copyright 2013 Facebook, Inc.\n\
*\n\
* Licensed under the Apache License, Version 2.0 (the "License");\n\
* you may not use this file except in compliance with the License.\n\
@@ -64,13 +61,13 @@ var basic = {
debug: false,
standalone: 'React',
transforms: [envify({NODE_ENV: 'development'})],
after: [es3ify.transform, simpleBannerify]
after: [simpleBannerify]
};
var min = _.merge({}, basic, {
var min = grunt.util._.merge({}, basic, {
outfile: './build/react.min.js',
debug: false,
transforms: [envify({NODE_ENV: 'production'}), uglifyify],
transforms: [envify({NODE_ENV: 'production'})],
after: [minify, bannerify]
});
@@ -81,7 +78,7 @@ var transformer = {
outfile: './build/JSXTransformer.js',
debug: false,
standalone: 'JSXTransformer',
after: [es3ify.transform, simpleBannerify]
after: [simpleBannerify]
};
var addons = {
@@ -93,34 +90,20 @@ var addons = {
standalone: 'React',
transforms: [envify({NODE_ENV: 'development'})],
packageName: 'React (with addons)',
after: [es3ify.transform, simpleBannerify]
after: [simpleBannerify]
};
var addonsMin = _.merge({}, addons, {
var addonsMin = grunt.util._.merge({}, addons, {
outfile: './build/react-with-addons.min.js',
debug: false,
transforms: [envify({NODE_ENV: 'production'}), uglifyify],
transforms: [envify({NODE_ENV: 'production'})],
after: [minify, bannerify]
});
var withCodeCoverageLogging = {
entries: [
'./build/modules/React.js'
],
outfile: './build/react.js',
debug: true,
standalone: 'React',
transforms: [
envify({NODE_ENV: 'development'}),
require('coverify')
]
};
module.exports = {
basic: basic,
min: min,
transformer: transformer,
addons: addons,
addonsMin: addonsMin,
withCodeCoverageLogging: withCodeCoverageLogging
addonsMin: addonsMin
};

View File

@@ -1,16 +0,0 @@
"use strict";
var grunt = require('grunt');
module.exports.generic = {
src: grunt.file.expand({
filter: function(path){
return !(/__\w+__|\btest\b/).test(path);
}
}, ['./build/modules/**/*.js']),
options: {
errorsOnly: false, // show only maintainability errors
cyclomatic: 3,
halstead: 8,
maintainability: 100
}
};

View File

@@ -10,7 +10,7 @@ module.exports = {
archive: './build/react-' + version + '.zip'
},
files: [
{cwd: './build/starter', src: ['**'], dest: 'react-' + version + '/'}
{cwd: './build/starter', src: ['**', '!examples/wrapup/**'], dest: 'react-' + version + '/'}
]
}
};
};

View File

@@ -1,43 +0,0 @@
'use strict';
var grunt = require('grunt');
var _ = require('lodash');
var rootIDs = [
"React",
"ReactWithAddons"
];
var normal = {
rootIDs: rootIDs,
getConfig: function() {
return {
commonerConfig: grunt.config.data.pkg.commonerConfig,
constants: {}
};
},
sourceDir: "src",
outputDir: "build/modules"
};
var test = {
rootIDs: rootIDs.concat([
"test/all.js",
"**/__tests__/*.js"
]),
getConfig: function() {
return _.merge({}, normal.getConfig(), {
mocking: true
});
},
sourceDir: "src",
outputDir: "build/modules"
};
module.exports = {
normal: normal,
test: test
};

77
grunt/config/jsx/jsx.js Normal file
View File

@@ -0,0 +1,77 @@
'use strict';
var grunt = require('grunt');
var rootIDs = [
"React",
"ReactWithAddons"
];
var getDebugConfig = function() {
return {
"debug": true,
"constants": {
"__VERSION__": grunt.config.data.pkg.version,
"__DEV__": true
}
};
};
var debug = {
rootIDs: rootIDs,
getConfig: getDebugConfig,
sourceDir: "src",
outputDir: "build/modules"
};
var jasmine = {
rootIDs: [
"all"
],
getConfig: getDebugConfig,
sourceDir: "vendor/jasmine",
outputDir: "build/jasmine"
};
var test = {
rootIDs: rootIDs.concat([
"test/all.js",
"**/__tests__/*.js"
]),
getConfig: function() {
return {
"debug": true,
"mocking": true,
"constants": {
"__VERSION__": grunt.config.data.pkg.version,
"__DEV__": true
}
};
},
sourceDir: "src",
outputDir: "build/modules"
};
var release = {
rootIDs: rootIDs,
getConfig: function() {
return {
"debug": false,
"constants": {
"__VERSION__": grunt.config.data.pkg.version,
"__DEV__": false
}
};
},
sourceDir: "src",
outputDir: "build/modules"
};
module.exports = {
debug: debug,
jasmine: jasmine,
test: test,
release: release
};

11
grunt/config/phantom.js Normal file
View File

@@ -0,0 +1,11 @@
var grunt = require("grunt");
exports.run = {
port: 8080,
harness: "test/phantom-harness.js",
// Run `grunt test --debug` to enable in-browser testing.
debug: !!grunt.option("debug"),
tests: [
"**/__tests__/*-test.js"
]
};

View File

@@ -1,105 +0,0 @@
'use strict';
module.exports = function(grunt){
var coverageWriteStream;
grunt.task.registerTask('finalize-coverage-stream', function(){
if (!coverageWriteStream) {
return;
}
var done = this.async();
coverageWriteStream.once('close', done);
coverageWriteStream.end();
coverageWriteStream = null;
});
function consoleLoggerMiddleware(req, res, next) {
if (!(req.method == 'POST' && req._parsedUrl.pathname.replace(/\//g,'') == 'console' && Array.isArray(req.body))) {
return next();
}
res.write('<!doctype html><meta charset=utf-8>');
res.end('Got it, thanks!');
req.body.forEach(function(log){
if (log.message.indexOf('not ok ') === 0) {
log.type = 'error';
} else if (log.message.indexOf('ok ') === 0) {
log.type = 'ok';
} else if (log.message.indexOf('COVER') === 0) {
log.type = 'coverage';
} else if (log.message.indexOf('DONE\t') === 0) {
log.type = 'coverage done';
}
if (log.type == 'error') {
grunt.log.error(log.message);
} else if (log.type == 'ok') {
grunt.log.ok(log.message);
} else if (log.type == 'log') {
grunt.log.writeln(log.message);
} else if (log.type == 'coverage') {
if (!coverageWriteStream) {
coverageWriteStream = require('fs').createWriteStream(__dirname + '/../../coverage.log');
}
coverageWriteStream.write(log.message + '\n');
} else if (log.type == 'coverage done') {
grunt.task.run('finalize-coverage-stream');
} else if (log.type == 'perf') {
grunt.event.emit('perf results', log.message);
} else {
grunt.verbose.writeln(log);
}
});
}
function testResultLoggerMiddleware(req, res, next) {
if (!(req.method == 'POST' && req._parsedUrl.pathname.indexOf('/reportTestResults') === 0)) {
return next();
}
res.write('<!doctype html><meta charset=utf-8>');
res.end('Got it, thanks!');
var logType = 'writeln';
var message = req.body;
if (req.body.type && req.body.message){
if (req.body.type == 'error') {
logType = 'error';
} else if (req.body.message.indexOf('ok') === 0) {
logType = 'ok';
} else if (req.body.message.indexOf('not ok') === 0) {
logType = 'error';
}
message = req.body.message;
}
if (typeof message != 'string') {
message = JSON.stringify(message, null, 2);
}
grunt.log[logType]('[%s][%s]', req.headers['user-agent'], Date.now(), message);
}
return {
server: {
options: {
base: '.',
hostname: '*',
port: 9999,
middleware: function(connect, options) {
connect.logger.token('user-agent', function(req, res) { return req.headers['user-agent']; });
connect.logger.token('timestamp', function(req, res) { return Date.now(); });
return [
connect.json(),
consoleLoggerMiddleware,
testResultLoggerMiddleware,
connect.logger({format:'[:user-agent][:timestamp] :method :url', stream:grunt.verbose}),
connect.static(options.base),
connect.directory(options.base)
];
}
}
}
};
};

View File

@@ -1,113 +0,0 @@
'use strict';
var grunt = require('grunt');
module.exports = function(props){
if (typeof props.url != 'string') {
throw TypeError('expected url string');
}
if ('isDoneTimeout' in props && typeof props.isDoneTimeout != 'number') {
throw TypeError('expected isDoneTimeout to be a number');
}
if ('onStart' in props && typeof props.onStart != 'function') {
throw TypeError('expected onStart to be a function');
}
if ('onComplete' in props && typeof props.onComplete != 'function') {
throw TypeError('expected onComplete to be a function');
}
if ('onError' in props && typeof props.onError != 'function') {
throw TypeError('expected onError to be a function');
}
var exports = {};
exports.local = {
webdriver: {
remote: { protocol: 'http:', hostname: '127.0.0.1', port: 9515, path: '/' }
},
url: props.url,
onStart: props.onStart,
onComplete: props.onComplete,
onError: props.onError,
isDoneTimeout: props.isDoneTimeout
};
if (grunt.option('debug')) {
exports.local.url += (exports.local.url.indexOf('?') == -1 ? '?' : '&') + 'debug=' + grunt.option('debug');
}
exports.saucelabs = {
webdriver: {
remote: {
/* https://github.com/admc/wd/blob/master/README.md#named-parameters */
user: process.env.SAUCE_USERNAME || 'React',
pwd: process.env.SAUCE_ACCESS_KEY || '339d32ca-d594-4570-a3c2-94c50a91919b',
protocol: 'http:',
hostname: 'ondemand.saucelabs.com',
port: '80',
path: '/wd/hub'
}
},
desiredCapabilities: {
"build": process.env.TRAVIS_BUILD_NUMBER || 'dev' + Date.now(),
"tunnel-identifier": process.env.TRAVIS_JOB_NUMBER || 'my awesome tunnel',
"browserName": "chrome"
},
url: exports.local.url,
onStart: function(browser){
grunt.log.writeln("Starting WebDriver Test. Watch results here: http://saucelabs.com/tests/" + browser.sessionID);
if (props.onStart) {
return props.onStart(browser);
}
},
onComplete: exports.local.onComplete,
onError: exports.local.onError,
isDoneTimeout: exports.local.isDoneTimeout
};
/* https://saucelabs.com/platforms */
exports.saucelabs_ios =
exports.saucelabs_ios7 = sauceItUp({ browserName: 'iphone', version: '7', platform:'OS X 10.9' });
exports.saucelabs_ios6_1 = sauceItUp({ browserName: 'iphone', version: '6.1', platform:'OS X 10.8' });
exports.saucelabs_ios6 = sauceItUp({ browserName: 'iphone', version: '6', platform:'OS X 10.8' });
exports.saucelabs_ios5_1 = sauceItUp({ browserName: 'iphone', version: '5.1', platform:'OS X 10.8' });
exports.saucelabs_ios5 = sauceItUp({ browserName: 'iphone', version: '5', platform:'OS X 10.6' });
exports.saucelabs_ios4 = sauceItUp({ browserName: 'iphone', version: '4', platform:'OS X 10.6' });
exports.saucelabs_ipad =
exports.saucelabs_ipad7 = sauceItUp({ browserName: 'ipad', version: '7', platform:'OS X 10.9' });
exports.saucelabs_ipad6_1 = sauceItUp({ browserName: 'ipad', version: '6.1', platform:'OS X 10.8' });
exports.saucelabs_ipad6 = sauceItUp({ browserName: 'ipad', version: '6', platform:'OS X 10.8' });
exports.saucelabs_ipad5_1 = sauceItUp({ browserName: 'ipad', version: '5.1', platform:'OS X 10.8' });
exports.saucelabs_ipad5 = sauceItUp({ browserName: 'ipad', version: '5', platform:'OS X 10.6' });
exports.saucelabs_ipad4 = sauceItUp({ browserName: 'ipad', version: '4', platform:'OS X 10.6' });
exports.saucelabs_android = sauceItUp({ browserName: 'android', version: '4.0', platform:'Linux' });
exports.saucelabs_android_tablet = sauceItUp({ browserName: 'android', version: '4.0', platform:'Linux', 'device-type':'tablet' });
exports.saucelabs_safari = sauceItUp({ browserName: 'safari' });
exports.saucelabs_chrome = sauceItUp({ browserName: 'chrome' });
exports.saucelabs_firefox = sauceItUp({ browserName: 'firefox' });
exports.saucelabs_ie =
exports.saucelabs_ie8 = sauceItUp({ browserName: 'internet explorer', version: 8 });
exports.saucelabs_ie9 = sauceItUp({ browserName: 'internet explorer', version: 9 });
exports.saucelabs_ie10 = sauceItUp({ browserName: 'internet explorer', version: 10 });
exports.saucelabs_ie11 = sauceItUp({ browserName: 'internet explorer', version: 11, platform:'Windows 8.1' });
function sauceItUp(desiredCapabilities) {
desiredCapabilities["build"] = exports.saucelabs.desiredCapabilities["build"];
desiredCapabilities["tunnel-identifier"] = exports.saucelabs.desiredCapabilities["tunnel-identifier"];
return {
webdriver: exports.saucelabs.webdriver,
url: exports.saucelabs.url,
onStart: exports.saucelabs.onStart,
onComplete: exports.saucelabs.onComplete,
onError: exports.saucelabs.onError,
isDoneTimeout: exports.saucelabs.isDoneTimeout,
desiredCapabilities: desiredCapabilities,
};
}
return exports;
}

View File

@@ -1,15 +0,0 @@
'use strict';
var grunt = require('grunt');
module.exports = require('./webdriver-all')({
url: "http://127.0.0.1:9999/test/index.html",
onComplete: function(passed){
if (!passed){
grunt.fatal("tests failed");
}
},
onError: function(error){
grunt.fatal(error);
}
});

View File

@@ -1,48 +0,0 @@
'use strict';
var grunt = require('grunt');
var tests = grunt.file.expand(__dirname + '/../../perf/tests/*');
var maxTime = 5;
var reactVersions = [
'edge',
'previous'
];
var params = []
.concat('headless=false')
.concat('maxTime=' + maxTime)
.concat(tests
.map(function(path){ return path.split(/tests./i).reverse()[0]; })
.map(encodeURIComponent)
.map(function(filename){ return 'test=' + filename; })
)
.concat(reactVersions
.map(encodeURIComponent)
.map(function(version){ return 'react=' + version }
)
);
module.exports = require('./webdriver-all')({
url: "http://127.0.0.1:9999/perf/index.html?" + params.join('&'),
isDoneTimeout: 15 * 60 * 1000,
onStart: function(){
grunt.event.on('perf results', function(results){
console.log(results);
});
},
onComplete: function(completedTestKeys){
grunt.verbose.writeln('onComplete ' + JSON.stringify(completedTestKeys));
},
onError: function(error){
grunt.fatal(error);
}
});

31
grunt/config/wrapup.js Normal file
View File

@@ -0,0 +1,31 @@
'use strict';
var grunt = require('grunt');
var UglifyJS = require('uglify-js');
function minify(src) {
return UglifyJS.minify(src, { fromString: true }).code;
}
// Our basic config which we'll add to to make our other builds
var basic = {
outfile: './build/react-global.js',
requires: {
React: './build/modules/React.js'
},
debug: true
};
module.exports = {
basic: basic
};
// Create minified versions of each build
for (var buildName in module.exports) {
var build = module.exports[buildName];
module.exports[buildName + '-min'] = grunt.util._.merge({}, build, {
outfile: build.outfile.replace('.js', '.min.js'),
debug: false,
after: minify
});
}

View File

@@ -46,9 +46,7 @@ module.exports = function() {
};
// TODO: make sure this works, test with this too
config.transforms.forEach(function(transform) {
bundle.transform({}, transform);
});
config.transforms.forEach(bundle.transform, bundle);
// Actually bundle it up
var _this = this;

View File

@@ -1,53 +0,0 @@
"use strict";
var grunt = require('grunt');
module.exports = function(){
var ROOT = require('path').normalize(__dirname + '/../..');
var done = this.async();
var uncoveredExpressionCount = 0;
var uncoveredLineCount = 0;
require('fs').createReadStream(ROOT + '/coverage.log')
.pipe(require('coverify/parse')(function(error, results){
if (error) {
grunt.fatal(error);
}
Object.keys(results)
.sort(function(a, b){
return results[a].length - results[b].length;
})
.reverse()
.forEach(function(path){
if (results[path].length === 0) {
return;
}
var relativePath = path.replace(ROOT, '');
uncoveredExpressionCount += results[path].length;
grunt.log.error(results[path].length + ' expressions not covered ' + relativePath);
results[path].forEach(function(c){
uncoveredLineCount += c.code.split('\n').length;
console.log('txmt://open?url=' + encodeURIComponent('file://' + path) + '&line=' + (c.lineNum+1) + '&column=' + (c.column[0]+2));
});
console.log('');
})
;
Object.keys(results).sort().forEach(function(path){
if (results[path].length > 0) {
return;
}
var relativePath = path.replace(ROOT, '');
grunt.log.ok('100% coverage ' + relativePath);
});
if (uncoveredExpressionCount > 0) {
grunt.log.error(uncoveredExpressionCount + ' expressions not covered');
}
if (uncoveredLineCount > 0) {
grunt.log.error(uncoveredLineCount + ' lines not covered');
}
done();
}));
};

Some files were not shown because too many files have changed in this diff Show More