Skip to content

Instantly share code, notes, and snippets.

@josephj
Last active August 27, 2015 12:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save josephj/70c2df5f889a32c545a1 to your computer and use it in GitHub Desktop.
Save josephj/70c2df5f889a32c545a1 to your computer and use it in GitHub Desktop.
'use strict';
/**
* <CodeMirror
* mode="text/css"
* value={that.state.customCss}
* onChange={that.handleEditorChange}/>
*/
// CodeMirror modules
import 'codemirror/lib/codemirror.css';
import 'codemirror/mode/javascript/javascript.js';
import 'codemirror/mode/css/css.js';
import 'codemirror/theme/ambiance.css';
import 'codemirror/addon/edit/matchbrackets.js';
import 'codemirror/addon/lint/lint.css';
import 'codemirror/addon/hint/javascript-hint.js';
import 'codemirror/addon/hint/css-hint.js';
import 'codemirror/addon/lint/lint.js';
import 'codemirror/addon/lint/javascript-lint.js';
import 'codemirror/addon/lint/json-lint.js';
import 'codemirror/addon/lint/css-lint.js';
import 'codemirror/addon/scroll/simplescrollbars.css';
import 'codemirror/addon/scroll/simplescrollbars.js';
// Tools
import React from 'react';
import _ from 'lodash';
import LogMixin from 'js/common/log-mixin';
import joinClasses from 'react/lib/joinClasses';
import CodeMirror from 'codemirror';
const IS_MOBILE = typeof navigator === 'undefined' || (
navigator.userAgent.match(/Android/i)
|| navigator.userAgent.match(/webOS/i)
|| navigator.userAgent.match(/iPhone/i)
|| navigator.userAgent.match(/iPad/i)
|| navigator.userAgent.match(/iPod/i)
|| navigator.userAgent.match(/BlackBerry/i)
|| navigator.userAgent.match(/Windows Phone/i)
);
module.exports = React.createClass({
//===================
// Properties
//===================
displayName: 'CodeMirror',
mixins: [LogMixin],
propTypes: {
indentUnit: React.PropTypes.number,
indentWithTabs: React.PropTypes.bool,
lineNumbers: React.PropTypes.bool,
lint: React.PropTypes.bool,
matchBrackets: React.PropTypes.bool,
mode: React.PropTypes.string,
onChange: React.PropTypes.func,
smartIndent: React.PropTypes.bool,
tabSize: React.PropTypes.number,
theme: React.PropTypes.string,
value: React.PropTypes.string,
},
//===================
// Core Methods
//===================
toString () {
return 'CodeMirror'
},
getDefaultProps () {
return {
gutters: ['CodeMirror-lint-markers'],
indentUnit: 4,
indentWithTabs: true,
lineNumbers: true,
lint: true,
matchBrackets: true,
mode: 'javascript',
scrollbarStyle: 'simple',
smartIndent: true,
tabSize: 4,
theme: 'ambiance'
}
},
render () {
let that = this,
props = that.props,
className = {},
style = {};
that.log('render() is executed');
_.assign(style, props.style);
delete props.style
className.wrapper = joinClasses(props.className);
return (
<div
ref="editor"
style={style}
className={className.wrapper}>
</div>
);
},
//===================
// Lifecycle Methods
//===================
componentDidMount () {
let that = this,
isTextarea = that.props.forceTextArea || IS_MOBILE;
that.log('componentDidMount() is executed');
if (!isTextarea) {
that.editor = CodeMirror(that.refs.editor.getDOMNode(), that.props);
that.editor.on('change', that.handleChange);
}
},
componentDidUpdate () {
let that = this,
nextValue,
prevValue;
that.log('componentDidUpdate() is executed');
if (!that.editor) {
return;
}
prevValue = that.editor.getValue();
nextValue = that.props.value;
if (prevValue === nextValue) {
return;
}
that.editor.setValue(that.props.value);
},
//================
// Event Handlers
//================
handleChange (e) {
let that = this,
prevValue,
nextValue;
that.log('handleChange() is executed');
// Stop if it's normal textarea
if (!that.editor) {
return;
}
prevValue = that.props.value;
nextValue = that.editor.getValue();
// Stop if previous value is same with current value
if (prevValue === nextValue) {
return;
}
that.props.onChange && that.props.onChange({target: {value: nextValue}});
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment