@samitouri / QOS-React-2 / commits / 71b585325c

docs add jsx->js tab to live editors

Cheng Lou committed Jan 17, 2014 at 01:53 UTC 71b585325ce7abc149fe848bb3fe119488ad8c3e
4 files changed +101 -46
docs/_css/react.scss
+14 -4
@@ -580,6 +580,11 @@ div.CodeMirror-linenumber:after {
580 border: none;
581 }
582
583 +/* hide the cursor. Mostly used when code's in plain JS */
584 +.CodeMirror-readonly div.CodeMirror-cursor {
585 + visibility: hidden;
586 +}
587 +
588 small code,
589 li code,
590 p code {
@@ -596,23 +601,28 @@ p code {
601 @include clearfix;
602 }
603
599 -.playground::before {
604 +.playground-tab {
605 border-bottom: none !important;
606 border-radius: 3px 3px 0 0;
602 - padding: 3px 7px;
607 + padding: 6px 8px;
608 font-size: 12px;
609 font-weight: bold;
610 color: #c2c0bc;
611 background-color: #f1ede4;
607 - content: 'Live editor';
612 + display: inline-block;
613 + cursor: pointer;
614 }
615
610 -.playground::before,
616 .playgroundCode,
617 +.playground-tab,
618 .playgroundPreview {
619 border: 1px solid rgba(16,16,16,0.1);
620 }
621
622 +.playground-tab-active {
623 + color: $darkestColor;
624 +}
625 +
626 .playgroundCode {
627 border-radius: 0 3px 3px 3px;
628 float: left;
docs/_js/examples/timer.js
+4 -3
@@ -3,6 +3,7 @@
3 */
4
5 var TIMER_COMPONENT = "\
6 +/** @jsx React.DOM */\n\
7 var Timer = React.createClass({\n\
8 getInitialState: function() {\n\
9 return {secondsElapsed: 0};\n\
@@ -17,13 +18,13 @@ var Timer = React.createClass({\n\
18 clearInterval(this.interval);\n\
19 },\n\
20 render: function() {\n\
20 - return React.DOM.div({},\n\
21 - 'Seconds Elapsed: ', this.state.secondsElapsed\n\
21 + return (\n\
22 + <div>Seconds Elapsed: {this.state.secondsElapsed}</div>\n\
23 );\n\
24 }\n\
25 });\n\
26 \n\
26 -React.renderComponent(Timer({}), mountNode);\
27 +React.renderComponent(<Timer />, mountNode);\
28 ";
29
30 React.renderComponent(
docs/_js/live_editor.js
+82 -38
@@ -14,10 +14,9 @@ var IS_MOBILE = (
14 );
15
16 var CodeMirrorEditor = React.createClass({
17 - componentDidMount: function(root) {
18 - if (IS_MOBILE) {
19 - return;
20 - }
17 + componentDidMount: function() {
18 + if (IS_MOBILE) return;
19 +
20 this.editor = CodeMirror.fromTextArea(this.refs.editor.getDOMNode(), {
21 mode: 'javascript',
22 lineNumbers: false,
@@ -26,15 +25,21 @@ var CodeMirrorEditor = React.createClass({
25 theme: 'solarized-light',
26 readOnly: this.props.readOnly
27 });
29 - this.editor.on('change', this.onChange);
30 - this.onChange();
28 + this.editor.on('change', this.handleChange);
29 + },
30 +
31 + componentDidUpdate: function() {
32 + if (this.props.readOnly) {
33 + this.editor.setValue(this.props.codeText);
34 + }
35 },
32 - onChange: function() {
33 - if (this.props.onChange) {
34 - var content = this.editor.getValue();
35 - this.props.onChange(content);
36 +
37 + handleChange: function() {
38 + if (!this.props.readOnly) {
39 + this.props.onChange && this.props.onChange(this.editor.getValue());
40 }
41 },
42 +
43 render: function() {
44 // wrap in a div to fully contain CodeMirror
45 var editor;
@@ -46,7 +51,7 @@ var CodeMirrorEditor = React.createClass({
51 }
52
53 return (
49 - <div className={this.props.className}>
54 + <div style={this.props.style} className={this.props.className}>
55 {editor}
56 </div>
57 );
@@ -67,7 +72,7 @@ var selfCleaningTimeout = {
72 var ReactPlayground = React.createClass({
73 mixins: [selfCleaningTimeout],
74
70 - MODES: {XJS: 'XJS', JS: 'JS'}, //keyMirror({XJS: true, JS: true}),
75 + MODES: {JSX: 'JSX', JS: 'JS'}, //keyMirror({JSX: true, JS: true}),
76
77 propTypes: {
78 codeText: React.PropTypes.string.isRequired,
@@ -84,15 +89,19 @@ var ReactPlayground = React.createClass({
89 },
90
91 getInitialState: function() {
87 - return {mode: this.MODES.XJS, code: this.props.codeText};
92 + return {
93 + mode: this.MODES.JSX,
94 + code: this.props.codeText,
95 + };
96 },
97
90 - bindState: function(name) {
91 - return function(value) {
92 - var newState = {};
93 - newState[name] = value;
94 - this.setState(newState);
95 - }.bind(this);
98 + handleCodeChange: function(value) {
99 + this.setState({code: value});
100 + this.executeCode();
101 + },
102 +
103 + handleCodeModeSwitch: function(mode) {
104 + this.setState({mode: mode});
105 },
106
107 compileCode: function() {
@@ -100,25 +109,53 @@ var ReactPlayground = React.createClass({
109 },
110
111 render: function() {
103 - var content;
104 - if (this.state.mode === this.MODES.XJS) {
105 - content =
106 - <CodeMirrorEditor
107 - onChange={this.bindState('code')}
108 - className="playgroundStage"
109 - codeText={this.state.code}
110 - />;
111 - } else if (this.state.mode === this.MODES.JS) {
112 - content =
113 - <div className="playgroundJS playgroundStage">
114 - {this.compileCode()}
115 - </div>;
116 - }
112 + var isJS = this.state.mode === this.MODES.JS;
113 + var compiledCode = '';
114 + try {
115 + compiledCode = this.compileCode();
116 + } catch (err) {}
117 +
118 + // we're creating both versions, to avoid the flicker when switching from
119 + // one view to another when CodeMirror recompiles
120 + var jsContent =
121 + <CodeMirrorEditor
122 + style={{display: isJS ? 'inherit' : 'none'}}
123 + className="playgroundStage CodeMirror-readonly"
124 + onChange={this.handleCodeChange}
125 + codeText={compiledCode}
126 + readOnly={true}
127 + />;
128 +
129 + var jsxContent =
130 + <CodeMirrorEditor
131 + style={{display: isJS ? 'none' : 'inherit'}}
132 + onChange={this.handleCodeChange}
133 + className="playgroundStage"
134 + codeText={this.state.code}
135 + />;
136 +
137 + var JSXTabClassName =
138 + 'playground-tab' + (isJS ? '' : ' playground-tab-active');
139 + var JSTabClassName =
140 + 'playground-tab' + (isJS ? ' playground-tab-active' : '');
141
142 return (
143 <div className="playground">
144 + <div>
145 + <div
146 + className={JSXTabClassName}
147 + onClick={this.handleCodeModeSwitch.bind(this, this.MODES.JSX)}>
148 + Live JSX Editor
149 + </div>
150 + <div
151 + className={JSTabClassName}
152 + onClick={this.handleCodeModeSwitch.bind(this, this.MODES.JS)}>
153 + Compiled JS
154 + </div>
155 + </div>
156 <div className="playgroundCode">
121 - {content}
157 + {jsxContent}
158 + {jsContent}
159 </div>
160 <div className="playgroundPreview">
161 <div ref="mount" />
@@ -126,12 +163,19 @@ var ReactPlayground = React.createClass({
163 </div>
164 );
165 },
166 +
167 componentDidMount: function() {
168 this.executeCode();
169 },
132 - componentDidUpdate: function() {
133 - this.executeCode();
170 +
171 + componentWillUpdate: function(nextProps, nextState) {
172 + // execute code only when the state's not being updated by switching tab
173 + // this avoids re-displaying the error, which comes after a certain delay
174 + if (this.state.mode === nextState.mode) {
175 + this.executeCode();
176 + };
177 },
178 +
179 executeCode: function() {
180 var mountNode = this.refs.mount.getDOMNode();
181
@@ -149,10 +193,10 @@ var ReactPlayground = React.createClass({
193 } else {
194 eval(compiledCode);
195 }
152 - } catch (e) {
196 + } catch (err) {
197 this.setTimeout(function() {
198 React.renderComponent(
155 - <div className="playgroundError">{e.toString()}</div>,
199 + <div className="playgroundError">{err.toString()}</div>,
200 mountNode
201 );
202 }, 500);
docs/_layouts/default.html
+1 -1
@@ -16,9 +16,9 @@
16 <link rel="shortcut icon" href="/react/favicon.ico">
17 <link rel="alternate" type="application/rss+xml" title="{{ site.name }}" href="{{ site.url }}{{ site.baseurl }}/feed.xml">
18
19 - <link rel="stylesheet" href="/react/css/react.css">
19 <link rel="stylesheet" href="/react/css/syntax.css">
20 <link rel="stylesheet" href="/react/css/codemirror.css">
21 + <link rel="stylesheet" href="/react/css/react.css">
22
23 <script type="text/javascript" src="//use.typekit.net/vqa1hcx.js"></script>
24 <script type="text/javascript">try{Typekit.load();}catch(e){}</script>