react-templates/playground/playground.js

273 lines
10 KiB
JavaScript

/*eslint-env browser*/
define(['react', 'react-dom', 'jquery', 'lodash', './playground-fiddle.rt', './playground.rt'], function (React, ReactDOM, $, _, pgFiddleTemplate, playgroundTemplate) {
'use strict'
//function emptyFunc() {
// return null;
//}
//function generateTemplateSource(html, editor, name) {
// var code = null;
// try {
// code = window.reactTemplates.convertTemplateToReact(html.trim().replace(/\r/g, ''), {modules: 'none', name: name});
// clearMessage(editor);
// } catch (e) {
// if (e.name === 'RTCodeError') {
// //index: -1 line: -1 message: "Document should have a root element" name: "RTCodeError"
// editor.annotate({line: e.line, message: e.message, index: e.index});
// } else {
// editor.annotate({line: 1, message: e.message});
// }
// //showMessage(editor, msg);
// console.log(e);
// }
// return code;
//}
function showMessage(editor, msg) {
if (editor && editor.showMessage) {
editor.annotate({line: 1, message: msg})
}
}
function clearMessage(editor) {
if (editor && editor.clearAnnotations) {
editor.clearAnnotations()
}
}
//function generateTemplateFunction(code) {
// try {
// var defineMap = {'react/addons': React, lodash: _};
// var define = function (requirementsNames, content) {
// var requirements = _.map(requirementsNames, function (reqName) {
// return defineMap[reqName];
// });
// return content.apply(this, requirements);
// };
// /*eslint no-eval:0*/
// var res = eval(code);
// return res;
// } catch (e) {
// console.log(e);
// return emptyFunc;
// }
//}
function generateRenderFunc(renderFunc) {
return function () {
var res = null
try {
res = renderFunc.apply(this)
} catch (e) {
res = React.DOM.div.apply(this, [{style: {color: 'red'}}, 'Exception:' + e.message])
}
return React.DOM.div.apply(this, _.flatten([
{key: 'result'},
res
]))
}
}
var templateHTML = '<div></div>'
var templateProps = 'var template = React.createClass({\n' +
' render: templateRT\n' +
'});'
//var selfCleaningTimeout = {
// componentDidUpdate: function() {
// clearTimeout(this.timeoutID);
// },
// setTimeout: function() {
// console.log('setTimeout');
// clearTimeout(this.timeoutID);
// this.timeoutID = setTimeout.apply(null, arguments);
// }
//};
var Playground = React.createClass({
displayName: 'Playground',
mixins: [React.addons.LinkedStateMixin],
propTypes: {
direction: React.PropTypes.oneOf(['horizontal', 'vertical']),
codeVisible: React.PropTypes.bool,
fiddle: React.PropTypes.bool,
templateHTML: React.PropTypes.string,
templateProps: React.PropTypes.string,
name: React.PropTypes.string
},
templateSource: '',
validHTML: true,
validProps: true,
setTimeout: function () {
//console.log('setTimeout');
clearTimeout(this.timeoutID)
this.timeoutID = setTimeout.apply(null, arguments)
},
getDefaultProps: function () {
return {
direction: 'horizontal', //vertical
codeVisible: true,
fiddle: false
}
},
getLayoutClass: function () {
return (this.props.direction === 'horizontal' && 'horizontal') || 'vertical' //eslint-disable-line no-extra-parens
},
//executeCode: function() {
// var mountNode = this.refs.mount.getDOMNode();
//
// try {
// React.unmountComponentAtNode(mountNode);
// } catch (e) { }
//
// try {
// var compiledCode = this.compileCode();
// if (this.props.renderCode) {
// React.render(
// React.createElement(CodeMirrorEditor, {codeText: compiledCode, readOnly: true}),
// mountNode
// );
// } else {
// eval(compiledCode);
// }
// } catch (err) {
// this.setTimeout(function() {
// React.render(
// React.createElement('div', {className: 'playgroundError'}, err.toString()),
// mountNode
// );
// }, 500);
// }
//},
getTabs: function () {
if (this.props.codeVisible) {
return [['templateHTML', 'Template'], ['templateProps', 'Class'], ['templateSource', 'Generated code']]
}
return [['templateHTML', 'Template'], ['templateSource', 'Generated code']]
},
updateSample: function (state) {
//try {
// React.unmountComponentAtNode(mountNode);
//} catch (e) { }
this.generateCode(state)
//this.sampleFunc = generateTemplateFunction(this.templateSource);
//this.validHTML = this.sampleFunc !== emptyFunc;
this.validHTML = true
this.sampleRender = generateRenderFunc(this.sampleFunc)
var editor
try {
this.validProps = true
//console.log(state.templateProps);
this.sample = eval('(function () {' + this.templateSource + '\n' + state.templateProps + '\n return React.createElement(' + state.name + ');})()') //eslint-disable-line no-eval
clearMessage(this.refs.editorCode)
} catch (e) {
this.validProps = false
this.sample = null
editor = this.refs.editorCode
this.showError(e, editor)
}
//classBase.render = this.sampleRender;
//this.sample = React.createFactory(React.createClass(classBase));
},
showError: function (e, editor) {
var mountNode = this.refs.mount
this.setTimeout(function () {
showMessage(editor, e.message)
ReactDOM.render(
React.createElement('div', {className: 'playground-error'}, e.toString()),
mountNode
)
}, 500)
},
showErrorAnnotation: function (annot, editor) {
var mountNode = this.refs.mount
this.setTimeout(function () {
editor.annotate(annot)
ReactDOM.render(
React.createElement('div', {className: 'playground-error'}, annot.message),
mountNode
)
}, 500)
},
clear: function () {
var currentState = {
templateHTML: templateHTML,
templateProps: templateProps
}
//this.updateSample(currentState);
this.setState(currentState)
},
generateCode: function (state) {
var html = state.templateHTML
var editor = this.refs.editorRT
var name = window.reactTemplates.normalizeName(state.name) + 'RT'
var code = null
try {
code = window.reactTemplates.convertTemplateToReact(html.trim().replace(/\r/g, ''), {modules: 'none', name: name})
clearMessage(editor)
} catch (e) {
var annot = e.name === 'RTCodeError' ? {line: e.line, message: e.message, index: e.index} : {line: 1, message: e.message}
this.showErrorAnnotation(annot, editor)
//showMessage(editor, msg);
console.log(e)
}
this.templateSource = code
},
getInitialState: function () {
var currentState = {
templateHTML: this.props.templateHTML || templateHTML,
templateProps: this.props.templateProps || templateProps,
name: this.props.name || 'template',
currentTab: 'templateHTML'
}
//this.updateSample(currentState);
return currentState
},
componentDidMount: function () {
if (this.props.fiddle) {
window.addEventListener('resize', this.calcSize)
this.calcSize()
}
this.updateSample(this.state)
this.renderSample()
},
renderSample: function () {
var mountNode = this.refs.mount
if (this.sample) {
ReactDOM.render(this.sample, mountNode)
}
},
componentDidUpdate: function () {
this.renderSample()
},
componentWillUnmount: function () {
window.removeEventListener('resize', this.calcSize)
},
calcSize: function () {
var contentHeight = $(window).height() - $('#header').height()
var height = contentHeight / 2 - 10
$('.code-area').each(function (/*i, k*/) {
$(this).height(height)
//console.log($(this).height());
})
this.refs.editorCode.editor.refresh()
this.refs.editorRT.editor.refresh()
this.refs.editorGenerated.editor.refresh()
},
componentWillUpdate: function (nextProps, nextState) {
if (nextState.templateHTML !== this.state.templateHTML || nextState.templateProps !== this.state.templateProps) {
this.updateSample(nextState)
}
},
render: function () {
this.generateCode(this.state)
var template = this.props.fiddle ? pgFiddleTemplate : playgroundTemplate
return template.apply(this)
}
})
return Playground
})