1
0
mirror of https://github.com/bobwen-dev/react-templates synced 2025-04-12 00:56:39 +02:00

add tabs to playground

This commit is contained in:
ido 2014-11-27 18:53:37 +02:00
parent e646677554
commit a62b54c520
6 changed files with 147 additions and 55 deletions

View File

@ -3,12 +3,24 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>React templates - Image Search Sample</title> <title>React templates - Image Search Sample</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap-theme.min.css">
<!-- Latest compiled and minified JavaScript -->
<link rel="stylesheet" href="playground/playground.css"/> <link rel="stylesheet" href="playground/playground.css"/>
</head> </head>
<body> <body>
<div id="playground"> <div id="playground">
</div> </div>
<script src="playground/main.browser.js"></script> <!--<script src="playground/bundle/reactTemplates.bundle.js"></script>-->
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<script src="playground/bundle/main.browser.js"></script>
</body> </body>
</html> </html>

View File

@ -1,7 +1,7 @@
/** /**
* Created by avim on 11/25/2014. * Created by avim on 11/25/2014.
*/ */
'use strict';
var React = require('react/addons'); var React = require('react/addons');
var _ = require('lodash'); var _ = require('lodash');
var brace = require('brace'); var brace = require('brace');
@ -11,29 +11,29 @@ require('brace/mode/html');
require('brace/theme/monokai'); require('brace/theme/monokai');
var editor = React.createClass({ var editor = React.createClass({
diplayName:"BraceEditor", displayName: 'BraceEditor',
getInitialState: function () { getInitialState: function () {
return { return {
editorId: _.uniqueId() editorId: _.uniqueId()
} };
}, },
componentWillMount: function () { componentWillMount: function () {
}, },
render: function () { render: function () {
var props = _.omit(this.props,['id','ref','key','value','valueLink','onChange']); var props = _.omit(this.props, ['id', 'ref', 'key', 'value', 'valueLink', 'onChange']);
props.id = this.state.editorId; props.id = this.state.editorId;
return React.DOM.div(props) return React.DOM.div(props);
}, },
componentWillUpdate: function (nextProps, nextState) { componentWillUpdate: function (nextProps/*, nextState*/) {
var value = nextProps.valueLink?nextProps.valueLink():nextProps.value; var value = nextProps.valueLink ? nextProps.valueLink() : nextProps.value;
if (this.editor && this.editor.getValue() != value ) { if (this.editor && this.editor.getValue() != value) {
this.editor.setValue(value,0); this.editor.setValue(value, 0);
} }
}, },
componentDidMount: function () { componentDidMount: function () {
this.editor = brace.edit(this.state.editorId); this.editor = brace.edit(this.state.editorId);
if (this.props.mode !== "html") { if (this.props.mode !== 'html') {
this.editor.getSession().setMode('ace/mode/javascript'); this.editor.getSession().setMode('ace/mode/javascript');
} else { } else {
this.editor.getSession().setMode('ace/mode/html'); this.editor.getSession().setMode('ace/mode/html');
@ -41,17 +41,17 @@ var editor = React.createClass({
this.editor.getSession().setUseWorker(false); this.editor.getSession().setUseWorker(false);
this.editor.setTheme('ace/theme/monokai'); this.editor.setTheme('ace/theme/monokai');
var value = this.props.valueLink?this.props.valueLink():this.props.value; var value = this.props.valueLink ? this.props.valueLink() : this.props.value;
this.editor.setValue(value,0); this.editor.setValue(value, 0);
if (this.props.readOnly) { if (this.props.readOnly) {
this.editor.setReadOnly(true); this.editor.setReadOnly(true);
} else { } else {
this.editor.setReadOnly(false); this.editor.setReadOnly(false);
this.editor.on("change", function(e) { this.editor.on('change', function (/*e*/) {
if (this.props.valueLink) { if (this.props.valueLink) {
this.props.valueLink(this.editor.getValue()); this.props.valueLink(this.editor.getValue());
} else if (this.props.onChange) { } else if (this.props.onChange) {
this.props.onChange({target:{value:this.editor.getValue()}}); this.props.onChange({target: {value: this.editor.getValue()}});
} }
}.bind(this)); }.bind(this));
} }

View File

@ -57,7 +57,19 @@ function generateRenderFunc(renderFunc) {
}; };
} }
var z = {getInitialState: function() {return {name: 'reactTemplates'};}}; var z = {getInitialState: function() {return {name: 'reactTemplates'};}};
var templateHTML = "<div>\n Have {_.filter(this.state.todos, {done:true}).length} todos done,\n and {_.filter(this.state.todos, {done:false}).length} not done\n <br/>\n <div rt-repeat=\"todo in this.state.todos\" key=\"{todo.key}\">\n <button onClick=\"(e)=>e.preventDefault(); this.remove(todo)\">x</button>\n <input type=\"checkbox\" checked=\"{todo.done}\" onChange=\"()=>this.toggleChecked(todoIndex)\"/>\n <span style=\"text-decoration: {todo.done ? 'line-through': 'none'}\">{todo.value}</span>\n </div>\n <input key=\"myinput\" type=\"text\" onKeyDown=\"(e) => if (e.keyCode == 13) { this.add(); }\" valueLink=\"{this.linkState('edited')}\"/>\n <button onClick=\"(e)=>e.preventDefault(); this.add()\" >Add</button><br/>\n <button onClick=\"(e)=>e.preventDefault(); this.clearDone()\">Clear done</button>\n</div>"; var templateHTML = '<div>\n' +
'Have {_.filter(this.state.todos, {done:true}).length} todos done,\n' +
'and {_.filter(this.state.todos, {done:false}).length} not done\n' +
' <br/>\n' +
' <div rt-repeat="todo in this.state.todos" key="{todo.key}">\n' +
' <button onClick="()=>this.remove(todo)">x</button>\n' +
' <input type="checkbox" checked="{todo.done}" onChange="()=>this.toggleChecked(todoIndex)"/>\n' +
' <span style="text-decoration: {todo.done ? \'line-through\': \'none\'}">{todo.value}</span>\n' +
' </div>\n' +
' <input key="myinput" type="text" onKeyDown="(e) => if (e.keyCode == 13) { e.preventDefault(); this.add(); }" valueLink="{this.linkState(\'edited\')}"/>\n' +
' <button onClick="()=>this.add()">Add</button><br/>\n' +
' <button onClick="()=>this.clearDone()">Clear done</button>\n' +
'</div>';
var templateProps = "{\n mixins: [React.addons.LinkedStateMixin],\n getInitialState: function () {\n return {edited: '', todos: [], counter: 0};\n },\n add: function () {\n if (this.state.edited.trim().length === 0) {\n return;\n }\n var newTodo = {value: this.state.edited, done: false, key: this.state.counter};\n this.setState({todos: this.state.todos.concat(newTodo), edited: '', counter: this.state.counter + 1});\n },\n remove: function (todo) {\n this.setState({todos: _.reject(this.state.todos, todo)});\n },\n toggleChecked: function (index) {\n var todos = _.cloneDeep(this.state.todos);\n todos[index].done = !todos[index].done;\n this.setState({todos: todos});\n },\n clearDone: function () {\n this.setState({todos: _.filter(this.state.todos, {done: false})});\n }\n}"; var templateProps = "{\n mixins: [React.addons.LinkedStateMixin],\n getInitialState: function () {\n return {edited: '', todos: [], counter: 0};\n },\n add: function () {\n if (this.state.edited.trim().length === 0) {\n return;\n }\n var newTodo = {value: this.state.edited, done: false, key: this.state.counter};\n this.setState({todos: this.state.todos.concat(newTodo), edited: '', counter: this.state.counter + 1});\n },\n remove: function (todo) {\n this.setState({todos: _.reject(this.state.todos, todo)});\n },\n toggleChecked: function (index) {\n var todos = _.cloneDeep(this.state.todos);\n todos[index].done = !todos[index].done;\n this.setState({todos: todos});\n },\n clearDone: function () {\n this.setState({todos: _.filter(this.state.todos, {done: false})});\n }\n}";
var Playground = React.createClass({ var Playground = React.createClass({

View File

@ -1,24 +1,41 @@
.hidden { /*.hidden {*/
display:none; /*display: none;*/
/*}*/
body {
padding: 20px;
}
.hiddenTab {
/*width: 0;*/
/*height: 0;*/
} }
.large-text-area { .large-text-area {
height:300px; height: 400px;
margin: 10px; margin: 10px;
} }
.code-area { .code-area {
width: 50%; width: 50%;
height:620px; height: 620px;
float:left; float: left;
} }
.result-area { .result-area {
width: 50%; width: 50%;
height: 620px; height: 620px;
float:left; float: left;
} }
.sample-view { .sample-view {
margin:10px; margin: 10px;
}
.sample-view button {
margin: 5px;
}
.sample-view input[type=checkbox] {
margin-right: 5px;
} }

View File

@ -1,35 +1,43 @@
<!DOCTYPE rt CodeEditor="./aceEditor"> <!DOCTYPE rt CodeEditor="./aceEditor">
<div> <div>
<div class="code-area"> <div id="myTab" role="tabpanel" class="code-area">
<h2>Template:</h2> <!-- Nav tabs -->
<CodeEditor class="large-text-area" style="border: {this.validHTML? '1px solid black':'2px solid red'};" <ul class="nav nav-pills" role="tablist">
<li role="presentation" class="active"><a href="#template" aria-controls="template" role="tab" data-toggle="tab">Template</a></li>
value="{this.state.templateHTML}" <li role="presentation"><a href="#classCode" aria-controls="classCode" role="tab" data-toggle="tab">Class</a></li>
mode="html" <li role="presentation"><a href="#generatedCode" aria-controls="generatedCode" role="tab" data-toggle="tab">Generated code</a></li>
onChange="(evt) => this.setState({'templateHTML':evt.target.value})" </ul>
/> <!-- Tab panes -->
<br/> <div class="tab-content">
<h2>Class:</h2> <div role="tabpanel" class="tab-pane active" id="template">
<CodeEditor class="large-text-area" style="border: {this.validProps? '1px solid black':'2px solid red'};" <CodeEditor class="large-text-area" style="border: {this.validHTML? '1px solid black':'2px solid red'};"
value="{this.state.templateProps}" value="{this.state.templateHTML}"
mode="javascript" mode="html"
onChange="(evt) => this.setState({'templateProps':evt.target.value})" onChange="(evt) => this.setState({'templateHTML':evt.target.value})"
/> />
</div>
<div role="tabpanel" class="tab-pane" id="classCode">
<CodeEditor class="large-text-area" style="border: {this.validProps? '1px solid black':'2px solid red'};"
value="{this.state.templateProps}"
mode="javascript"
onChange="(evt) => this.setState({'templateProps':evt.target.value})"
/>
</div>
<div role="tabpanel" class="tab-pane" id="generatedCode">
<CodeEditor class="large-text-area" style="border:1px solid black;"
value="{this.templateSource}"
mode="javascript"
readOnly="{true}"
/>
</div>
</div>
</div> </div>
<div key="result-area" class="result-area"> <div key="result-area" class="result-area well">
<h2>Generated code:</h2>
<CodeEditor class="large-text-area" style="border:1px solid black;"
value="{this.templateSource}"
mode="javascript"
readOnly="{true}"
/>
<br/> <br/>
<h2>Preview:</h2> <h2>Preview:</h2>
<div class="sample-view"> <form class="sample-view" onSubmit="(e) => e.preventDefault();">
<this.sample key="sample"> <this.sample key="sample">
</this.sample> </this.sample>
</div> </form>
</div> </div>
</div> </div>

View File

@ -8,27 +8,70 @@ function onChange1(evt) {
function onChange2(evt) { function onChange2(evt) {
this.setState({ 'templateProps': evt.target.value }); this.setState({ 'templateProps': evt.target.value });
} }
function onSubmit3(e) {
e.preventDefault();
}
module.exports = function () { module.exports = function () {
return React.DOM.div({}, React.DOM.div({ 'className': 'code-area' }, React.DOM.h2({}, 'Template:'), CodeEditor({ return React.DOM.div({}, React.DOM.div({
'id': 'myTab',
'role': 'tabpanel',
'className': 'code-area'
} /* Nav tabs */, React.DOM.ul({
'className': 'nav nav-pills',
'role': 'tablist'
}, React.DOM.li({
'role': 'presentation',
'className': 'active'
}, React.DOM.a({
'href': '#template',
'aria-controls': 'template',
'role': 'tab',
'data-toggle': 'tab'
}, 'Template')), React.DOM.li({ 'role': 'presentation' }, React.DOM.a({
'href': '#classCode',
'aria-controls': 'classCode',
'role': 'tab',
'data-toggle': 'tab'
}, 'Class')), React.DOM.li({ 'role': 'presentation' }, React.DOM.a({
'href': '#generatedCode',
'aria-controls': 'generatedCode',
'role': 'tab',
'data-toggle': 'tab'
}, 'Generated code'))) /* Tab panes */, React.DOM.div({ 'className': 'tab-content' }, React.DOM.div({
'role': 'tabpanel',
'className': 'tab-pane active',
'id': 'template'
}, CodeEditor({
'className': 'large-text-area', 'className': 'large-text-area',
'style': { border: this.validHTML ? '1px solid black' : '2px solid red' }, 'style': { border: this.validHTML ? '1px solid black' : '2px solid red' },
'value': this.state.templateHTML, 'value': this.state.templateHTML,
'mode': 'html', 'mode': 'html',
'onChange': onChange1.bind(this) 'onChange': onChange1.bind(this)
}), React.DOM.br({}), React.DOM.h2({}, 'Class:'), CodeEditor({ })), React.DOM.div({
'role': 'tabpanel',
'className': 'tab-pane',
'id': 'classCode'
}, CodeEditor({
'className': 'large-text-area', 'className': 'large-text-area',
'style': { border: this.validProps ? '1px solid black' : '2px solid red' }, 'style': { border: this.validProps ? '1px solid black' : '2px solid red' },
'value': this.state.templateProps, 'value': this.state.templateProps,
'mode': 'javascript', 'mode': 'javascript',
'onChange': onChange2.bind(this) 'onChange': onChange2.bind(this)
})), React.DOM.div({ })), React.DOM.div({
'key': 'result-area', 'role': 'tabpanel',
'className': 'result-area' 'className': 'tab-pane',
}, React.DOM.h2({}, 'Generated code:'), CodeEditor({ 'id': 'generatedCode'
}, CodeEditor({
'className': 'large-text-area', 'className': 'large-text-area',
'style': { border: '1px solid black' }, 'style': { border: '1px solid black' },
'value': this.templateSource, 'value': this.templateSource,
'mode': 'javascript', 'mode': 'javascript',
'readOnly': true 'readOnly': true
}), React.DOM.br({}), React.DOM.h2({}, 'Preview:'), React.DOM.div({ 'className': 'sample-view' }, this.sample({ 'key': 'sample' })))); })))), React.DOM.div({
'key': 'result-area',
'className': 'result-area well'
}, React.DOM.br({}), React.DOM.h2({}, 'Preview:'), React.DOM.form({
'className': 'sample-view',
'onSubmit': onSubmit3.bind(this)
}, this.sample({ 'key': 'sample' }))));
}; };