React Rich Text Editor PoC

Playing with the concept of a ReactJS based rich text editor, where content is stored as text with side-along annotations. Perhaps this would be better with a contentEditable DIV, but that's not supported in ReactJS right now (https://github.com/facebook/react/issues/278)

by edwardmsmith

CSS

.input {
    font: 16px helvetica, arial;
    border:none;
    margin:0;
    padding:0;
    position: absolute;
    top:0;
    left:0;
    height: 250px;
    width: 400px;
    background:transparent;
    color:rgba(0, 0, 0, 0);
}
.output {
    font: 16px helvetica, arial;
    margin:0;
    padding:0;
    position: absolute;
    top:0;
    left:0;
    height: 250px;
    width: 400px;
    color: black;
}

JavaScript

String.prototype.splice = function( idx, rem, s ) {
    return (this.slice(0,idx) + s + this.slice(idx + Math.abs(rem)));
};

var MainV = React.createClass({
    getInitialState: function() {
        return {
            content: 'Enter something', 
            annotations: [], 
            selection: {start:0, end:0}
        }
    },
    handleKeyDown: function(e) {
        if (e.ctrlKey && e.keyCode === 66 && (this.state.selection.start < this.state.selection.end)) {
            console.log("KeyUp!");
        
            var annotations = this.state.annotations.slice(0);
            annotations.push({
                start: this.state.selection.start,
                end: this.state.selection.end,
                type: 'bold'
            });
            this.setState({annotations: annotations});
        }
        console.log(this.state);
    },
    handleChange: function(e) {
        console.log("Change!");
        // content = this.state.content;
        this.setState({content: e.target.value});
    },
    handleSelect: function(e) {
        var selectedText = e.target.value.substring(e.target.selectionStart,e.target.selectionEnd);
        this.setState({
            selection: {start: e.target.selectionStart,
                        end: e.target.selectionEnd}
        });
        console.log("Select from " + e.target.selectionStart + " to " + e.target.selectionEnd);
    },
    
    render: function() {
        var outputContent = this.state.content;
        // If the selection is collapsed, insert the cursor char
        if (this.state.selection.start === this.state.selection.end) {
            outputContent = outputContent.splice(this.state.selection.start,0,'\u2038');
            console.log(outputContent);
        }
        return React.DOM.div({className: 'editor'}, null, [    
            // TODO: Apply annotations to output
            // TODO: Apply cursor to ouput
            React.DOM.div({
                ref: 'output',
                className:...