GithubHelp home page GithubHelp logo

Comments (8)

brandondurham avatar brandondurham commented on April 19, 2024 1

I honestly can’t help but think it has something to do with my project. Some kind of collision. I just can’t seem to find it. Either way, here is the actual component code:

import config from '../../config';
import React, { Component, PropTypes } from 'react';
import { Editor, EditorState, ContentState, RichUtils, convertFromRaw, convertToRaw } from 'draft-js';
import Select from 'react-select';
import classNames from 'classnames';
const styles = require('./Editor.css');
import {
    Button
} from 'components';

/**
 * Default Content
 * @type {Object}
 */
const rawContent = {
    blocks: [
        {
            text: (
                'Alpha Bravo Charlie Delta Echo Foxtrot Golf Hotel India ' +
                'Juliet Kilo Lima Mike November Oscar Papa Quebec Romeo Sierra ' +
                'Tango Uniform Victor Whiskey Xylophone Yankee Zulu Jackdaws ' +
                'love my big sphinx of quartz. Victors flank gypsy who mixed ' +
                'up on job quiz. Wolves exit quickly as fanged zoo chimps ' +
                'jabber? Five jumbo oxen graze quietly with packs of dogs. ' +
                'Grumpy wizards make toxic brew for the evil queen and jack.'
            ),
            type: 'unstyled',
            entityRanges: [{offset: 12, length: 14, key: 'first'}],
        },
        {
            text: '',
            type: 'unstyled',
        },
        {
            text: (
                'Lazy movers* quit hard packing of jewelry boxes: ban foul, ' +
                'toxic smogs which quickly jeopardize lives. Hark! 483 toxic ' +
                'jungle water vipers quietly drop on zebras for 107 meals! ' +
                'New farm hand, picking just six quinces, proves strong but ' +
                'lazy; back in my quaint garden, 62% jaunty zinnias vie with ' +
                'flaunting phlox. Waltz, nymph, for quick jigs vex Bud. Crazy ' +
                'Fredericka’s bought many very exquisite opal jewels. Jolly ' +
                'housewives made inexpensive “meals” using quick-frozen ' +
                'vegetables. Sixty zippers were quickly picked from the woven ' +
                'jute bag. Jaded zombies acted quaintly but kept driving their ' +
                '$59 oxen forward.'
            ),
            type: 'unstyled',
            entityRanges: [{offset: 28, length: 6, key: 'second'}],
        },
        {
            text: '',
            type: 'unstyled',
        },
        {
            text: (
                'Six big juicy steaks sizzled in a pan as five workmen left ' +
                'the quarry. Will Major Douglas be expected to take this ' +
                'true/false quiz very soon? A (mad) boxer [shot] a quick, ' +
                'gloved {jab} to of the jaw of his dizzy opponent. Jimmy and ' +
                'Zack, the police explained, were last seen diving into a ' +
                'field of buttered quahogs. The jukebox music puzzled a gentle ' +
                'visitor from a quaint valley town.'
            ),
            type: 'unstyled',
            entityRanges: [{offset: 30, length: 13, key: 'third'}],
        },
    ],
    entityMap: {
        first: {
            type: 'TOKEN',
            mutability: 'IMMUTABLE',
        },
        second: {
            type: 'TOKEN',
            mutability: 'MUTABLE',
        },
        third: {
            type: 'TOKEN',
            mutability: 'SEGMENTED',
        },
    },
};

/**
 * Inline Styles
 * @type {Object}
 */
const styleMap = {
    CODE: { fontFamily: '"Operator Mono", monospace', fontSize: 16 },
    LINEHEIGHT: { lineHeight: 2 },
    FONT_OPERATOR: { fontFamily: 'Operator', fontWeight: 800 },
    FONT_SIZE_9: { fontSize: 9 },
    FONT_SIZE_10: { fontSize: 10 },
    FONT_SIZE_11: { fontSize: 11 },
    FONT_SIZE_12: { fontSize: 12 },
    FONT_SIZE_14: { fontSize: 14 },
    FONT_SIZE_16: { fontSize: 16 },
    FONT_SIZE_18: { fontSize: 18 },
    FONT_SIZE_24: { fontSize: 24 },
    FONT_SIZE_30: { fontSize: 30 },
    FONT_SIZE_36: { fontSize: 36 },
    FONT_SIZE_48: { fontSize: 48 },
    FONT_SIZE_60: { fontSize: 60 },
    FONT_SIZE_72: { fontSize: 72 },
    FONT_SIZE_84: { fontSize: 84 },
    FONT_SIZE_96: { fontSize: 96 },
};

/**
 * Block styles
 * @param  {object} block
 * @return {string}
 */
function getBlockStyle(block) {
    switch (block.getType()) {
        case 'blockquote':
            return [styles.Blockquote];
        case 'alignleft':
            return [styles.AlignLeft];
        case 'aligncenter':
            return [styles.AlignCenter];
        case 'alignright':
            return [styles.AlignRight];
        default:
            return null;
    }
}


/**
 * Block Style Element Buttons
 * Toolbar buttons for all block-level elements.
 */
const BLOCK_TYPES = [
    { label: 'H1', style: 'header-one' },
    { label: 'H2', style: 'header-two' },
    { label: 'Blockquote', style: 'blockquote' },
    { label: 'UL', style: 'unordered-list-item' },
    { label: 'OL', style: 'ordered-list-item' },
    { label: 'Code Block', style: 'code-block' },
    { label: 'Align Left', style: 'alignleft' },
    { label: 'Align Center', style: 'aligncenter' },
    { label: 'Align Right', style: 'alignright' },
];
const BlockStyleControls = (props) => {
    const {editorState} = props;
    const selection = editorState.getSelection();
    const blockType = editorState
        .getCurrentContent()
        .getBlockForKey(selection.getStartKey())
        .getType();

    return (
        <div className={styles.ToolbarRow}>
            {BLOCK_TYPES.map((type, index) =>
                <Button
                    active={type.style === blockType}
                    key={index}
                    label={type.label}
                    onToggle={props.onToggle}
                    style={type.style}
                />
            )}
        </div>
    );
};

/**
 * Inline Style Buttons
 * Toolbar buttons for all inline style elements.
 */
const INLINE_STYLES = [
    {label: 'Bold', style: 'BOLD'},
    {label: 'Italic', style: 'ITALIC'},
    {label: 'Underline', style: 'UNDERLINE'},
    {label: 'Monospace', style: 'CODE'},
    {label: 'Line Height', style: 'LINEHEIGHT'}
];
const InlineStyleControls = (props) => {
    const currentStyle = props.editorState.getCurrentInlineStyle();
    return (
        <div className={styles.ToolbarRow}>
            {INLINE_STYLES.map((type, index) =>
                <Button
                    active={currentStyle.has(type.style)}
                    key={index}
                    label={type.label}
                    onToggle={props.onToggle}
                    style={type.style}
                />
            )}
        </div>
    );
};

/**
 * The Editor
 * The master Editor React component.
 * Consumes the Toolbar and Editor components.
 */
export default class TheEditor extends Component {

    static propTypes = {
        onToggle: PropTypes.func
    };

    state = {
        editorState: EditorState.createWithContent(ContentState.createFromBlockArray(convertFromRaw(rawContent)))
    };

    onChange = (editorState) => {
        this.setState({editorState});
    };

    focus = () => {
        this.refs.editor.focus();
    };

    handleKeyCommand = (command) => {
        const {editorState} = this.state;
        const newState = RichUtils.handleKeyCommand(editorState, command);
        if (newState) {
            this.onChange(newState);
            return true;
        }
        return false;
    }

    toggleBlockType = (type) => {
        this.onChange(
            RichUtils.toggleBlockType(
                this.state.editorState,
                type
            )
        );
    }

    toggleInlineStyle = (style) => {
        this.onChange(
            RichUtils.toggleInlineStyle(
                this.state.editorState,
                style
            )
        );
    }

    render() {
        const { editorState } = this.state;

        const contentState = editorState.getCurrentContent();
        const editorClasses = classNames({
            [styles.Editor]: true,
            [styles['Editor--hidePlaceholder']]: !contentState.hasText() && contentState.getBlockMap().first().getType() !== 'unstyled'
        });

        return (
            <div className={styles.Base}>
                <div className={styles.Toolbar}>
                    <BlockStyleControls
                        editorState={editorState}
                        onToggle={this.toggleBlockType}
                    />
                    <InlineStyleControls
                        editorState={editorState}
                        onToggle={this.toggleInlineStyle}
                    />
                    <div className={styles.ToolbarRow}>
                        <Select
                            clearable={false}
                            onChange={(item) => {
                                this.onChange(
                                    RichUtils.toggleInlineStyle(
                                        this.state.editorState,
                                        `FONT_SIZE_${item.value}`
                                    )
                                );
                            }}
                            // onFocus={this.focus}
                            options={config.toolbarOptions.fontSize}
                            placeholder="Multiple…"
                            searchable
                            value={'18px'}
                        />
                        <Button
                            label="Get Raw Content"
                            onToggle={() => {
                                const content = this.state.editorState.getCurrentContent();
                                console.log(convertToRaw(content));
                            }}
                        />
                    </div>
                </div>
                <div className={editorClasses} onClick={this.focus}>
                    <Editor
                        blockStyleFn={getBlockStyle}
                        customStyleMap={styleMap}
                        editorState={editorState}
                        handleKeyCommand={this.handleKeyCommand}
                        onChange={this.onChange}
                        ref="editor"
                        spellCheck={false}
                        stripPastedStyles
                    />
                </div>
            </div>
        );
    }
}

… and my package.json dependencies, in case you spot a culprit in there.

  "dependencies": {
    "babel": "5.8.29",
    "babel-plugin-typecheck": "2.0.0",
    "body-parser": "1.14.1",
    "classnames": "2.2.3",
    "compression": "1.6.0",
    "draft-js": "^0.1.0",
    "express": "4.13.3",
    "express-session": "1.12.1",
    "file-loader": "0.8.5",
    "history": "1.17.0",
    "hoist-non-react-statics": "1.0.3",
    "http-proxy": "1.12.0",
    "invariant": "2.2.0",
    "jquery": "2.2.0",
    "jss": "3.2.0",
    "jss-vendor-prefixer": "1.0.1",
    "lodash": "4.0.0",
    "lru-memoize": "1.0.0",
    "map-props": "1.0.0",
    "multireducer": "1.0.2",
    "piping": "0.3.0",
    "pretty-error": "1.2.0",
    "query-string": "3.0.0",
    "react": "0.14.7",
    "react-dom": "0.14.7",
    "react-helmet": "2.2.0",
    "react-inline-css": "2.0.0",
    "react-jss": "2.0.1",
    "react-onclickout": "2.0.4",
    "react-redux": "4.0.0",
    "react-router": "1.0.3",
    "react-select": "^1.0.0-beta8",
    "redux": "3.0.4",
    "redux-batched-actions": "^0.1.2",
    "redux-router": "1.0.0-beta5",
    "scroll-behavior": "0.3.0",
    "serialize-javascript": "1.1.2",
    "serve-favicon": "2.3.0",
    "socket.io": "1.3.7",
    "socket.io-client": "1.3.7",
    "superagent": "1.4.0",
    "url-loader": "0.5.7",
    "warning": "2.1.0",
    "webpack-isomorphic-tools": "2.2.18"
  },
  "devDependencies": {
    "autoprefixer": "6.3.1",
    "babel-core": "5.8.33",
    "babel-eslint": "4.1.7",
    "babel-loader": "5.3.3",
    "babel-plugin-react-transform": "1.1.1",
    "babel-runtime": "5.8.29",
    "better-npm-run": "0.0.4",
    "chai": "3.3.0",
    "clean-webpack-plugin": "0.1.6",
    "concurrently": "0.1.1",
    "css-loader": "0.23.1",
    "eslint": "1.10.3",
    "eslint-config-airbnb": "0.1.0",
    "eslint-loader": "1.0.0",
    "eslint-plugin-import": "0.8.0",
    "eslint-plugin-react": "3.5.0",
    "extract-text-webpack-plugin": "0.9.1",
    "happypack": "^1.1.3",
    "imports-loader": "0.6.5",
    "json-loader": "0.5.4",
    "karma": "0.13.10",
    "karma-cli": "0.1.1",
    "karma-mocha": "0.2.0",
    "karma-mocha-reporter": "1.1.1",
    "karma-phantomjs-launcher": "0.2.1",
    "karma-sourcemap-loader": "0.3.5",
    "karma-webpack": "1.7.0",
    "mocha": "2.3.3",
    "node-sass": "3.4.2",
    "postcss": "5.0.14",
    "postcss-loader": "0.8.0",
    "precss": "1.4.0",
    "progress-bar-webpack-plugin": "^1.3.0",
    "react-a11y": "0.2.6",
    "react-addons-test-utils": "0.14.0",
    "react-transform-catch-errors": "1.0.0",
    "react-transform-hmr": "1.0.1",
    "redbox-react": "1.1.1",
    "redux-devtools": "3.1.1",
    "redux-devtools-dock-monitor": "1.1.0",
    "redux-devtools-log-monitor": "1.0.4",
    "sinon": "1.17.2",
    "strip-loader": "0.1.0",
    "style-loader": "0.13.0",
    "timekeeper": "0.0.5",
    "webpack": "1.12.9",
    "webpack-dev-middleware": "1.4.0",
    "webpack-hot-middleware": "2.5.0"
  }

from draft-js.

hellendag avatar hellendag commented on April 19, 2024

Very interesting, thanks for the report. I'm taking a look now.

from draft-js.

sophiebits avatar sophiebits commented on April 19, 2024

Can you run a Chrome timeline profile to see what's taking the time?

from draft-js.

hellendag avatar hellendag commented on April 19, 2024

At first glance, it looks like we have a bottleneck during CharacterMetadata creation.

from draft-js.

brandondurham avatar brandondurham commented on April 19, 2024

Quick timeline snapshot. Digging in…

image

from draft-js.

hellendag avatar hellendag commented on April 19, 2024

The bottleneck seems to be in the Map lookup within immutable-js. The keys themselves in the CharacterMetadata pool are pretty small Maps, so this ideally shouldn't be so costly.

from draft-js.

birledan avatar birledan commented on April 19, 2024

hello @brandondurham. I need to do the alignment in draft.js, you did an interesting method, can you provide the whole exemple? thank you.

from draft-js.

mitermayer avatar mitermayer commented on April 19, 2024

I no longer seem to be able to reproduce this, feel free to re-open or create a new issue if you can reproduce this again

from draft-js.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.