Skip to content

Commit

Permalink
docs add jsx->js tab to live editors
Browse files Browse the repository at this point in the history
  • Loading branch information
chenglou committed Jan 17, 2014
1 parent a05cef4 commit 71b5853
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 46 deletions.
18 changes: 14 additions & 4 deletions docs/_css/react.scss
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,11 @@ div.CodeMirror-linenumber:after {
border: none;
}

/* hide the cursor. Mostly used when code's in plain JS */
.CodeMirror-readonly div.CodeMirror-cursor {
visibility: hidden;
}

small code,
li code,
p code {
Expand All @@ -596,23 +601,28 @@ p code {
@include clearfix;
}

.playground::before {
.playground-tab {
border-bottom: none !important;
border-radius: 3px 3px 0 0;
padding: 3px 7px;
padding: 6px 8px;
font-size: 12px;
font-weight: bold;
color: #c2c0bc;
background-color: #f1ede4;
content: 'Live editor';
display: inline-block;
cursor: pointer;
}

.playground::before,
.playgroundCode,
.playground-tab,
.playgroundPreview {
border: 1px solid rgba(16,16,16,0.1);
}

.playground-tab-active {
color: $darkestColor;
}

.playgroundCode {
border-radius: 0 3px 3px 3px;
float: left;
Expand Down
7 changes: 4 additions & 3 deletions docs/_js/examples/timer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

var TIMER_COMPONENT = "\
/** @jsx React.DOM */\n\
var Timer = React.createClass({\n\
getInitialState: function() {\n\
return {secondsElapsed: 0};\n\
Expand All @@ -17,13 +18,13 @@ var Timer = React.createClass({\n\
clearInterval(this.interval);\n\
},\n\
render: function() {\n\
return React.DOM.div({},\n\
'Seconds Elapsed: ', this.state.secondsElapsed\n\
return (\n\
<div>Seconds Elapsed: {this.state.secondsElapsed}</div>\n\
);\n\
}\n\
});\n\
\n\
React.renderComponent(Timer({}), mountNode);\
React.renderComponent(<Timer />, mountNode);\
";

React.renderComponent(
Expand Down
120 changes: 82 additions & 38 deletions docs/_js/live_editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ var IS_MOBILE = (
);

var CodeMirrorEditor = React.createClass({
componentDidMount: function(root) {
if (IS_MOBILE) {
return;
}
componentDidMount: function() {
if (IS_MOBILE) return;

this.editor = CodeMirror.fromTextArea(this.refs.editor.getDOMNode(), {
mode: 'javascript',
lineNumbers: false,
Expand All @@ -26,15 +25,21 @@ var CodeMirrorEditor = React.createClass({
theme: 'solarized-light',
readOnly: this.props.readOnly
});
this.editor.on('change', this.onChange);
this.onChange();
this.editor.on('change', this.handleChange);
},

componentDidUpdate: function() {
if (this.props.readOnly) {
this.editor.setValue(this.props.codeText);
}
},
onChange: function() {
if (this.props.onChange) {
var content = this.editor.getValue();
this.props.onChange(content);

handleChange: function() {
if (!this.props.readOnly) {
this.props.onChange && this.props.onChange(this.editor.getValue());
}
},

render: function() {
// wrap in a div to fully contain CodeMirror
var editor;
Expand All @@ -46,7 +51,7 @@ var CodeMirrorEditor = React.createClass({
}

return (
<div className={this.props.className}>
<div style={this.props.style} className={this.props.className}>
{editor}
</div>
);
Expand All @@ -67,7 +72,7 @@ var selfCleaningTimeout = {
var ReactPlayground = React.createClass({
mixins: [selfCleaningTimeout],

MODES: {XJS: 'XJS', JS: 'JS'}, //keyMirror({XJS: true, JS: true}),
MODES: {JSX: 'JSX', JS: 'JS'}, //keyMirror({JSX: true, JS: true}),

propTypes: {
codeText: React.PropTypes.string.isRequired,
Expand All @@ -84,54 +89,93 @@ var ReactPlayground = React.createClass({
},

getInitialState: function() {
return {mode: this.MODES.XJS, code: this.props.codeText};
return {
mode: this.MODES.JSX,
code: this.props.codeText,
};
},

bindState: function(name) {
return function(value) {
var newState = {};
newState[name] = value;
this.setState(newState);
}.bind(this);
handleCodeChange: function(value) {
this.setState({code: value});
this.executeCode();
},

handleCodeModeSwitch: function(mode) {
this.setState({mode: mode});
},

compileCode: function() {
return this.props.transformer(this.state.code);
},

render: function() {
var content;
if (this.state.mode === this.MODES.XJS) {
content =
<CodeMirrorEditor
onChange={this.bindState('code')}
className="playgroundStage"
codeText={this.state.code}
/>;
} else if (this.state.mode === this.MODES.JS) {
content =
<div className="playgroundJS playgroundStage">
{this.compileCode()}
</div>;
}
var isJS = this.state.mode === this.MODES.JS;
var compiledCode = '';
try {
compiledCode = this.compileCode();
} catch (err) {}

// we're creating both versions, to avoid the flicker when switching from
// one view to another when CodeMirror recompiles
var jsContent =
<CodeMirrorEditor
style={{display: isJS ? 'inherit' : 'none'}}
className="playgroundStage CodeMirror-readonly"
onChange={this.handleCodeChange}
codeText={compiledCode}
readOnly={true}
/>;

var jsxContent =
<CodeMirrorEditor
style={{display: isJS ? 'none' : 'inherit'}}
onChange={this.handleCodeChange}
className="playgroundStage"
codeText={this.state.code}
/>;

var JSXTabClassName =
'playground-tab' + (isJS ? '' : ' playground-tab-active');
var JSTabClassName =
'playground-tab' + (isJS ? ' playground-tab-active' : '');

return (
<div className="playground">
<div>
<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">
{content}
{jsxContent}
{jsContent}
</div>
<div className="playgroundPreview">
<div ref="mount" />
</div>
</div>
);
},

componentDidMount: function() {
this.executeCode();
},
componentDidUpdate: function() {
this.executeCode();

componentWillUpdate: function(nextProps, nextState) {
// execute code only when the state's not being updated by switching tab
// this avoids re-displaying the error, which comes after a certain delay
if (this.state.mode === nextState.mode) {
this.executeCode();
};
},

executeCode: function() {
var mountNode = this.refs.mount.getDOMNode();

Expand All @@ -149,10 +193,10 @@ var ReactPlayground = React.createClass({
} else {
eval(compiledCode);
}
} catch (e) {
} catch (err) {
this.setTimeout(function() {
React.renderComponent(
<div className="playgroundError">{e.toString()}</div>,
<div className="playgroundError">{err.toString()}</div>,
mountNode
);
}, 500);
Expand Down
2 changes: 1 addition & 1 deletion docs/_layouts/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
<link rel="shortcut icon" href="/react/favicon.ico">
<link rel="alternate" type="application/rss+xml" title="{{ site.name }}" href="{{ site.url }}{{ site.baseurl }}/feed.xml">

<link rel="stylesheet" href="/react/css/react.css">
<link rel="stylesheet" href="/react/css/syntax.css">
<link rel="stylesheet" href="/react/css/codemirror.css">
<link rel="stylesheet" href="/react/css/react.css">

<script type="text/javascript" src="//use.typekit.net/vqa1hcx.js"></script>
<script type="text/javascript">try{Typekit.load();}catch(e){}</script>
Expand Down

0 comments on commit 71b5853

Please sign in to comment.