@@ -14,10 +14,9 @@ var IS_MOBILE = (
14
14
) ;
15
15
16
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
+
21
20
this . editor = CodeMirror . fromTextArea ( this . refs . editor . getDOMNode ( ) , {
22
21
mode : 'javascript' ,
23
22
lineNumbers : false ,
@@ -26,15 +25,21 @@ var CodeMirrorEditor = React.createClass({
26
25
theme : 'solarized-light' ,
27
26
readOnly : this . props . readOnly
28
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
+ }
31
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 ( ) ) ;
36
40
}
37
41
} ,
42
+
38
43
render : function ( ) {
39
44
// wrap in a div to fully contain CodeMirror
40
45
var editor ;
@@ -46,7 +51,7 @@ var CodeMirrorEditor = React.createClass({
46
51
}
47
52
48
53
return (
49
- < div className = { this . props . className } >
54
+ < div style = { this . props . style } className = { this . props . className } >
50
55
{ editor }
51
56
</ div >
52
57
) ;
@@ -67,7 +72,7 @@ var selfCleaningTimeout = {
67
72
var ReactPlayground = React . createClass ( {
68
73
mixins : [ selfCleaningTimeout ] ,
69
74
70
- MODES : { XJS : 'XJS ' , JS : 'JS' } , //keyMirror({XJS : true, JS: true}),
75
+ MODES : { JSX : 'JSX ' , JS : 'JS' } , //keyMirror({JSX : true, JS: true}),
71
76
72
77
propTypes : {
73
78
codeText : React . PropTypes . string . isRequired ,
@@ -84,54 +89,93 @@ var ReactPlayground = React.createClass({
84
89
} ,
85
90
86
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
+ } ;
88
96
} ,
89
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 } ) ;
96
105
} ,
97
106
98
107
compileCode : function ( ) {
99
108
return this . props . transformer ( this . state . code ) ;
100
109
} ,
101
110
102
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' : '' ) ;
117
141
118
142
return (
119
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 >
120
156
< div className = "playgroundCode" >
121
- { content }
157
+ { jsxContent }
158
+ { jsContent }
122
159
</ div >
123
160
< div className = "playgroundPreview" >
124
161
< div ref = "mount" />
125
162
</ div >
126
163
</ div >
127
164
) ;
128
165
} ,
166
+
129
167
componentDidMount : function ( ) {
130
168
this . executeCode ( ) ;
131
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
+ } ;
134
177
} ,
178
+
135
179
executeCode : function ( ) {
136
180
var mountNode = this . refs . mount . getDOMNode ( ) ;
137
181
@@ -149,10 +193,10 @@ var ReactPlayground = React.createClass({
149
193
} else {
150
194
eval ( compiledCode ) ;
151
195
}
152
- } catch ( e ) {
196
+ } catch ( err ) {
153
197
this . setTimeout ( function ( ) {
154
198
React . renderComponent (
155
- < div className = "playgroundError" > { e . toString ( ) } </ div > ,
199
+ < div className = "playgroundError" > { err . toString ( ) } </ div > ,
156
200
mountNode
157
201
) ;
158
202
} , 500 ) ;
0 commit comments