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>