Created
February 26, 2016 04:03
-
-
Save hellendag/6cd425613caabb7f238d to your computer and use it in GitHub Desktop.
Revisions
-
Isaac Salier-Hellendag created this gist
Feb 26, 2016 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,223 @@ <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Draft • Decorators</title> <link rel="stylesheet" href="../../dist/Draft.css" /> </head> <body> <div id="target"></div> <script src="../../node_modules/react/dist/react.js"></script> <script src="../../node_modules/react-dom/dist/react-dom.js"></script> <script src="../../node_modules/immutable/dist/immutable.js"></script> <script src="../../node_modules/babel-core/browser.js"></script> <script src="../../dist/Draft.js"></script> <script type="text/babel"> 'use strict'; const {CompositeDecorator, Editor, EditorState, Modifier, SelectionState} = Draft; const Draggable = (props) => { const onDragStart = (e) => { e.dataTransfer.dropEffect = 'move'; e.dataTransfer.setData("text", props.block.key); }; return ( <div contentEditable={false} onDragStart={onDragStart} draggable="true" style={styles.draggable} /> ) }; class MarkdownEditorExample extends React.Component { constructor(props) { super(props); this.state = { editorState: EditorState.createEmpty(), }; this.focus = () => this.refs.editor.focus(); this.onChange = (editorState) => this.setState({editorState}); this.logState = () => console.log(this.state.editorState.toJS()); this.drop = this._drop.bind(this); this.blockRenderer = (contentBlock) => { const type = contentBlock.getType(); if (type === 'draggable') { return { component: Draggable, props: { onDrop: this.drop, } }; } } } addBlock() { const {editorState} = this.state; const contentState = editorState.getCurrentContent(); const selectionState = editorState.getSelection(); const afterRemoval = Modifier.removeRange( contentState, selectionState, 'backward' ); const targetSelection = afterRemoval.getSelectionAfter(); const afterSplit = Modifier.splitBlock( afterRemoval, targetSelection ); const insertionTarget = afterSplit.getSelectionAfter(); const insertText = Modifier.insertText( afterSplit, insertionTarget, ' ' ); const asMedia = Modifier.setBlockType( insertText, insertText.getSelectionAfter(), 'draggable' ); this.setState({ editorState: EditorState.push( editorState, asMedia, 'insert-fragment' ), }); } _drop(e, dropSelection) { const blockKey = e.dataTransfer.getData("text"); // Set timeout to allow cursor/selection to move to drop location // Get content, selection, block const {editorState} = this.state; const content = editorState.getCurrentContent(); const block = content.getBlockForKey(blockKey); const draggedRange = new SelectionState({ anchorKey: blockKey, anchorOffset: 0, focusKey: blockKey, focusOffset: block.getLength(), isBackward: false, }); // Split on drop location and set block type const afterFirstSplit = Modifier.splitBlock(content, dropSelection); const targetSelection = afterFirstSplit.getSelectionAfter(); const afterSecondSplit = Modifier.splitBlock( afterFirstSplit, targetSelection ); const afterMove = Modifier.moveText( afterSecondSplit, draggedRange, targetSelection ); const resetAsDraggable = Modifier.setBlockType( afterMove, afterMove.getSelectionAfter(), block.getType() ); const blockAfterDraggable = resetAsDraggable.getBlockAfter(blockKey); const cursorKey = blockAfterDraggable.getKey(); const moveSelection = resetAsDraggable.merge({ selectionBefore: dropSelection, selectionAfter: new SelectionState({ anchorKey: cursorKey, anchorOffset: 0, focusKey: cursorKey, focusOffset: 0, isBackward: false, }), }); this.setState({ editorState: EditorState.push( editorState, moveSelection, 'insert-fragment' ), }); return true; } render() { return ( <div style={styles.root}> <div style={styles.editor} onClick={this.focus} onDragOver={(e) => e.preventDefault()}> <Editor blockRendererFn={this.blockRenderer} editorState={this.state.editorState} handleDrop={this.drop} onChange={this.onChange} placeholder="Write a tweet..." ref="editor" spellCheck={true} /> </div> <input onClick={this.logState} style={styles.button} type="button" value="Log State" /> <input onClick={this.addBlock.bind(this)} style={styles.button} type="button" value="Add block" /> </div> ); } } const styles = { root: { fontFamily: '\'Helvetica\', sans-serif', padding: 20, width: 600, }, editor: { border: '1px solid #ddd', cursor: 'text', fontSize: 16, minHeight: 40, padding: 10, }, draggable: { backgroundColor: 'rgba(98, 177, 254, 1.0)', width: 40, height: 40, }, button: { marginTop: 10, textAlign: 'center', } }; ReactDOM.render( <MarkdownEditorExample />, document.getElementById('target') ); </script> </body> </html>