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>
<meta charset="utf-8">
<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"/>
</head>
<body>
<div id="playground">
</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>
</html>

View File

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

View File

@ -57,7 +57,19 @@ function generateRenderFunc(renderFunc) {
};
}
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 Playground = React.createClass({

View File

@ -1,24 +1,41 @@
.hidden {
display:none;
/*.hidden {*/
/*display: none;*/
/*}*/
body {
padding: 20px;
}
.hiddenTab {
/*width: 0;*/
/*height: 0;*/
}
.large-text-area {
height:300px;
height: 400px;
margin: 10px;
}
.code-area {
width: 50%;
height:620px;
float:left;
height: 620px;
float: left;
}
.result-area {
width: 50%;
height: 620px;
float:left;
float: left;
}
.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">
<div>
<div class="code-area">
<h2>Template:</h2>
<CodeEditor class="large-text-area" style="border: {this.validHTML? '1px solid black':'2px solid red'};"
value="{this.state.templateHTML}"
mode="html"
onChange="(evt) => this.setState({'templateHTML':evt.target.value})"
/>
<br/>
<h2>Class:</h2>
<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 id="myTab" role="tabpanel" class="code-area">
<!-- Nav tabs -->
<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>
<li role="presentation"><a href="#classCode" aria-controls="classCode" role="tab" data-toggle="tab">Class</a></li>
<li role="presentation"><a href="#generatedCode" aria-controls="generatedCode" role="tab" data-toggle="tab">Generated code</a></li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="template">
<CodeEditor class="large-text-area" style="border: {this.validHTML? '1px solid black':'2px solid red'};"
value="{this.state.templateHTML}"
mode="html"
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 key="result-area" class="result-area">
<h2>Generated code:</h2>
<CodeEditor class="large-text-area" style="border:1px solid black;"
value="{this.templateSource}"
mode="javascript"
readOnly="{true}"
/>
<div key="result-area" class="result-area well">
<br/>
<h2>Preview:</h2>
<div class="sample-view">
<form class="sample-view" onSubmit="(e) => e.preventDefault();">
<this.sample key="sample">
</this.sample>
</div>
</form>
</div>
</div>

View File

@ -8,27 +8,70 @@ function onChange1(evt) {
function onChange2(evt) {
this.setState({ 'templateProps': evt.target.value });
}
function onSubmit3(e) {
e.preventDefault();
}
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',
'style': { border: this.validHTML ? '1px solid black' : '2px solid red' },
'value': this.state.templateHTML,
'mode': 'html',
'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',
'style': { border: this.validProps ? '1px solid black' : '2px solid red' },
'value': this.state.templateProps,
'mode': 'javascript',
'onChange': onChange2.bind(this)
})), React.DOM.div({
'key': 'result-area',
'className': 'result-area'
}, React.DOM.h2({}, 'Generated code:'), CodeEditor({
'role': 'tabpanel',
'className': 'tab-pane',
'id': 'generatedCode'
}, CodeEditor({
'className': 'large-text-area',
'style': { border: '1px solid black' },
'value': this.templateSource,
'mode': 'javascript',
'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' }))));
};