From 71b585325ce7abc149fe848bb3fe119488ad8c3e Mon Sep 17 00:00:00 2001 From: Cheng Lou Date: Fri, 17 Jan 2014 01:53:26 -0800 Subject: [PATCH] docs add jsx->js tab to live editors --- docs/_css/react.scss | 18 ++++-- docs/_js/examples/timer.js | 7 ++- docs/_js/live_editor.js | 120 +++++++++++++++++++++++++------------ docs/_layouts/default.html | 2 +- 4 files changed, 101 insertions(+), 46 deletions(-) diff --git a/docs/_css/react.scss b/docs/_css/react.scss index d130086fc9..daa000270a 100644 --- a/docs/_css/react.scss +++ b/docs/_css/react.scss @@ -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 { @@ -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; diff --git a/docs/_js/examples/timer.js b/docs/_js/examples/timer.js index 685e57e705..00e60f9591 100644 --- a/docs/_js/examples/timer.js +++ b/docs/_js/examples/timer.js @@ -3,6 +3,7 @@ */ var TIMER_COMPONENT = "\ +/** @jsx React.DOM */\n\ var Timer = React.createClass({\n\ getInitialState: function() {\n\ return {secondsElapsed: 0};\n\ @@ -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\ +
Seconds Elapsed: {this.state.secondsElapsed}
\n\ );\n\ }\n\ });\n\ \n\ -React.renderComponent(Timer({}), mountNode);\ +React.renderComponent(, mountNode);\ "; React.renderComponent( diff --git a/docs/_js/live_editor.js b/docs/_js/live_editor.js index e51bfabfb7..5f582b400a 100644 --- a/docs/_js/live_editor.js +++ b/docs/_js/live_editor.js @@ -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, @@ -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); }, - onChange: function() { - if (this.props.onChange) { - var content = this.editor.getValue(); - this.props.onChange(content); + + componentDidUpdate: function() { + if (this.props.readOnly) { + this.editor.setValue(this.props.codeText); } }, + + 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; @@ -46,7 +51,7 @@ var CodeMirrorEditor = React.createClass({ } return ( -
+
{editor}
); @@ -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, @@ -84,15 +89,19 @@ 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() { @@ -100,25 +109,53 @@ var ReactPlayground = React.createClass({ }, render: function() { - var content; - if (this.state.mode === this.MODES.XJS) { - content = - ; - } else if (this.state.mode === this.MODES.JS) { - content = -
- {this.compileCode()} -
; - } + 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 = + ; + + var jsxContent = + ; + + var JSXTabClassName = + 'playground-tab' + (isJS ? '' : ' playground-tab-active'); + var JSTabClassName = + 'playground-tab' + (isJS ? ' playground-tab-active' : ''); return (
+
+
+ Live JSX Editor +
+
+ Compiled JS +
+
- {content} + {jsxContent} + {jsContent}
@@ -126,12 +163,19 @@ var ReactPlayground = React.createClass({
); }, + 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(); @@ -149,10 +193,10 @@ var ReactPlayground = React.createClass({ } else { eval(compiledCode); } - } catch (e) { + } catch (err) { this.setTimeout(function() { React.renderComponent( -
{e.toString()}
, +
{err.toString()}
, mountNode ); }, 500); diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html index 15177f3862..9cc8bef4c8 100644 --- a/docs/_layouts/default.html +++ b/docs/_layouts/default.html @@ -16,9 +16,9 @@ - +