draft-js#SelectionState JavaScript Examples

The following examples show how to use draft-js#SelectionState. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: EditorUtilities.js    From wix-style-react with MIT License 6 votes vote down vote up
_attachLinkEntityToText = (editorState, { text, url }) => {
  const contentState = editorState.getCurrentContent();
  const selectionState = editorState.getSelection();
  const contentStateWithEntity = contentState.createEntity('LINK', 'MUTABLE', {
    url,
  });
  const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
  const startPosition = selectionState.getStartOffset();
  const endPosition = startPosition + text.length;

  // A key for the block that containing the start of the selection range
  const blockKey = selectionState.getStartKey();

  // Replaces the content in specified selection range with text
  const contentStateWithText = Modifier.replaceText(
    contentState,
    selectionState,
    text,
  );

  const newSelectionState = new SelectionState({
    anchorOffset: startPosition,
    anchorKey: blockKey,
    focusOffset: endPosition,
    focusKey: blockKey,
  });

  const newEditorState = EditorState.push(
    editorState,
    contentStateWithText,
    'insert-characters',
  );

  return RichUtils.toggleLink(newEditorState, newSelectionState, entityKey);
}
Example #2
Source File: plugin.js    From react-mui-draft-wysiwyg with MIT License 5 votes vote down vote up
EditorLink = ({ contentState, entityKey, blockKey, start, end, children }) => {
    const [anchorEl, setAnchorEl] = React.useState(null);
    const editor = useEditor();
    const editorFocus = useEditorFocus();
    const { url } = contentState.getEntity(entityKey).getData();

    const showOptions = (ev) => {
        setAnchorEl(ev.currentTarget);
    };

    const hideOptions = () => {
        setAnchorEl(null);
    };

    const openLink = (ev) => {
        ev.preventDefault();
        ev.stopPropagation();
        window.open(url, '_blank');
    };

    const removeLink = (ev) => {
        ev.preventDefault();
        ev.stopPropagation();
        const linkSelection = SelectionState.createEmpty(blockKey).merge({
            anchorKey: blockKey,
            anchorOffset: start,
            focusKey: blockKey,
            focusOffset: end,
        });

        editor.onChange(RichUtils.toggleLink(editor.editorState, linkSelection, null));
        editorFocus();
    };

    return (
        <React.Fragment>
            <Link
                href={url}
                rel="noopener noreferrer"
                target="_blank"
                aria-label={url}
                onClick={showOptions}>
                {children}
            </Link>
            <Popover
                open={Boolean(anchorEl)}
                onClose={hideOptions}
                anchorEl={anchorEl}
                anchorOrigin={{
                    vertical: 'bottom',
                    horizontal: 'center',
                }}
                transformOrigin={{
                    vertical: 'top',
                    horizontal: 'center',
                }}>
                <ButtonGroup size="small" aria-label="Link options">
                    <Button onClick={openLink} title={`Open ${url}`}>
                        <LaunchIcon />
                    </Button>
                    <Button onClick={removeLink} title="Remove link">
                        <LinkOffIcon />
                    </Button>
                </ButtonGroup>
            </Popover>
        </React.Fragment>
    );
}
Example #3
Source File: convertFromHTML.js    From the-eye-knows-the-garbage with MIT License 5 votes vote down vote up
convertFromHTML = function convertFromHTML(_ref2) {
  var _ref2$htmlToStyle = _ref2.htmlToStyle,
      htmlToStyle = _ref2$htmlToStyle === void 0 ? defaultHTMLToStyle : _ref2$htmlToStyle,
      _ref2$htmlToEntity = _ref2.htmlToEntity,
      htmlToEntity = _ref2$htmlToEntity === void 0 ? defaultHTMLToEntity : _ref2$htmlToEntity,
      _ref2$textToEntity = _ref2.textToEntity,
      textToEntity = _ref2$textToEntity === void 0 ? defaultTextToEntity : _ref2$textToEntity,
      _ref2$htmlToBlock = _ref2.htmlToBlock,
      htmlToBlock = _ref2$htmlToBlock === void 0 ? defaultHTMLToBlock : _ref2$htmlToBlock;
  return function (html) {
    var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
      flat: false
    };
    var DOMBuilder = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : getSafeBodyFromHTML;
    var generateKey = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : genKey;
    var contentState = ContentState.createFromText('');

    var createEntityWithContentState = function createEntityWithContentState() {
      if (contentState.createEntity) {
        var _contentState;

        contentState = (_contentState = contentState).createEntity.apply(_contentState, arguments);
        return contentState.getLastCreatedEntityKey();
      }

      return Entity.create.apply(Entity, arguments);
    };

    var getEntityWithContentState = function getEntityWithContentState() {
      if (contentState.getEntity) {
        var _contentState2;

        return (_contentState2 = contentState).getEntity.apply(_contentState2, arguments);
      }

      return Entity.get.apply(Entity, arguments);
    };

    var mergeEntityDataWithContentState = function mergeEntityDataWithContentState() {
      if (contentState.mergeEntityData) {
        var _contentState3;

        contentState = (_contentState3 = contentState).mergeEntityData.apply(_contentState3, arguments);
        return;
      }

      Entity.mergeData.apply(Entity, arguments);
    };

    var replaceEntityDataWithContentState = function replaceEntityDataWithContentState() {
      if (contentState.replaceEntityData) {
        var _contentState4;

        contentState = (_contentState4 = contentState).replaceEntityData.apply(_contentState4, arguments);
        return;
      }

      Entity.replaceData.apply(Entity, arguments);
    };

    var contentBlocks = convertFromHTMLtoContentBlocks(html, handleMiddleware(htmlToStyle, baseProcessInlineTag), handleMiddleware(htmlToEntity, defaultHTMLToEntity), handleMiddleware(textToEntity, defaultTextToEntity), handleMiddleware(htmlToBlock, baseCheckBlockType), createEntityWithContentState, getEntityWithContentState, mergeEntityDataWithContentState, replaceEntityDataWithContentState, options, DOMBuilder, generateKey);
    var blockMap = BlockMapBuilder.createFromArray(contentBlocks);
    var firstBlockKey = contentBlocks[0].getKey();
    return contentState.merge({
      blockMap: blockMap,
      selectionBefore: SelectionState.createEmpty(firstBlockKey),
      selectionAfter: SelectionState.createEmpty(firstBlockKey)
    });
  };
}
Example #4
Source File: plugin.js    From react-mui-draft-wysiwyg with MIT License 4 votes vote down vote up
EditorImage = ({ src, width, height, contentState, block }) => {
    const [anchorEl, setAnchorEl] = React.useState(null);
    const [infoAnchorEl, setInfoAnchorEl] = React.useState(null);
    const editor = useEditor();
    const editorFocus = useEditorFocus();
    const classes = useStyles();

    const showOptions = (ev) => {
        setAnchorEl(ev.currentTarget);
        setInfoAnchorEl(ev.currentTarget);
    };

    const hideOptions = () => {
        setAnchorEl(null);
        setInfoAnchorEl(null);
    };

    const imageAlign = (ev, align) => {
        ev.preventDefault();
        ev.stopPropagation();
        const imageSelection = SelectionState.createEmpty(block.getKey()).merge({
            anchorKey: block.getKey(),
            anchorOffset: 0,
            focusKey: block.getKey(),
            focusOffset: block.getLength(),
        });

        const newContentState = Modifier.setBlockData(contentState, imageSelection, {
            textAlign: align,
        });
        editor.onChange(EditorState.push(editor.editorState, newContentState, 'change-block-data'));
        editorFocus();
    };

    const removeImage = (ev) => {
        ev.preventDefault();
        ev.stopPropagation();
        const imageSelection = SelectionState.createEmpty(block.getKey()).merge({
            anchorKey: block.getKey(),
            anchorOffset: 0,
            focusKey: block.getKey(),
            focusOffset: block.getLength(),
        });

        let newContentState = Modifier.removeRange(contentState, imageSelection, 'forward');

        const blockMap = newContentState.getBlockMap().delete(block.getKey());

        const firstBlock = newContentState.getFirstBlock();

        const selectionToStart = SelectionState.createEmpty(firstBlock.getKey()).merge({
            anchorKey: firstBlock.getKey(),
            anchorOffset: 0,
            focusKey: firstBlock.getKey(),
            focusOffset: 0,
        });

        newContentState = newContentState.merge({ blockMap, selectionAfter: selectionToStart });

        editor.onChange(EditorState.push(editor.editorState, newContentState, 'remove-range'));
        editorFocus();
    };

    if (!src) return null;

    return (
        <React.Fragment>
            <img alt={src} src={src} width={width} height={height} onClick={showOptions} />
            <Popover
                open={Boolean(infoAnchorEl)}
                onClose={hideOptions}
                anchorEl={infoAnchorEl}
                anchorOrigin={{
                    vertical: 'top',
                    horizontal: 'right',
                }}
                transformOrigin={{
                    vertical: 'bottom',
                    horizontal: 'right',
                }}>
                <Typography color="textSecondary" variant="body1" className={classes.imgInfo}>
                    {width}&nbsp;x&nbsp;{height}
                </Typography>
            </Popover>
            <Popover
                open={Boolean(anchorEl)}
                onClose={hideOptions}
                anchorEl={anchorEl}
                anchorOrigin={{
                    vertical: 'bottom',
                    horizontal: 'center',
                }}
                transformOrigin={{
                    vertical: 'top',
                    horizontal: 'center',
                }}>
                <ButtonGroup
                    size="small"
                    aria-label={editor.translate('controls.image.labels.editOptions')}>
                    <Button
                        onClick={(ev) => imageAlign(ev, 'left')}
                        title={editor.translate('controls.image.actions.alignLeft')}>
                        <ArrowLeftIcon />
                        <ImageIcon />
                    </Button>
                    <Button
                        onClick={(ev) => imageAlign(ev, 'center')}
                        title={editor.translate('controls.image.actions.alignCenter')}>
                        <ArrowLeftIcon />
                        <ImageIcon />
                        <ArrowRightIcon />
                    </Button>
                    <Button
                        onClick={(ev) => imageAlign(ev, 'right')}
                        title={editor.translate('controls.image.actions.alignRight')}>
                        <ImageIcon />
                        <ArrowRightIcon />
                    </Button>
                    <Button
                        onClick={() => {
                            hideOptions();
                            editor.showResizeImageDialog(block.getEntityAt(0));
                        }}
                        title={editor.translate('controls.image.actions.resize')}>
                        <PhotoSizeSelectLargeIcon />
                    </Button>
                    <Button
                        onClick={removeImage}
                        title={editor.translate('controls.image.actions.remove')}>
                        <DeleteIcon />
                    </Button>
                </ButtonGroup>
            </Popover>
        </React.Fragment>
    );
}
Example #5
Source File: Mention.react.js    From spring-boot-ecommerce with Apache License 2.0 4 votes vote down vote up
Mention = function (_React$Component) {
  _inherits(Mention, _React$Component);

  function Mention(props) {
    _classCallCheck(this, Mention);

    var _this = _possibleConstructorReturn(this, _React$Component.call(this, props));

    _this.onEditorChange = function (editorState) {
      var selection = editorState.getSelection();
      _this._decorator = editorState.getDecorator();
      var content = editorState.getCurrentContent();

      if (_this.props.onChange) {
        _this.setState({
          selection: selection
        }, function () {
          _this.props.onChange(content, exportContent(content));
        });
      } else {
        _this.setState({
          editorState: editorState,
          selection: selection
        });
      }
    };

    _this.onFocus = function (e) {
      if (_this.props.onFocus) {
        _this.props.onFocus(e);
      }
    };

    _this.onBlur = function (e) {
      if (_this.props.onBlur) {
        _this.props.onBlur(e);
      }
    };

    _this.onKeyDown = function (e) {
      if (_this.props.onKeyDown) {
        _this.props.onKeyDown(e);
      }
    };

    _this.reset = function () {
      /*eslint-disable*/
      _this._editor.Reset();
      /*eslint-enable*/
    };

    _this.mention = createMention({
      prefix: _this.getPrefix(props),
      tag: props.tag,
      mode: props.mode,
      mentionStyle: props.mentionStyle
    });

    _this.Suggestions = _this.mention.Suggestions;
    _this.plugins = [_this.mention];

    _this.state = {
      suggestions: props.suggestions,
      value: props.value && EditorState.createWithContent(props.value, new CompositeDecorator(_this.mention.decorators)),
      selection: SelectionState.createEmpty()
    };

    if (typeof props.defaultValue === 'string') {
      // eslint-disable-next-line
      console.warn('The property `defaultValue` now allow `EditorState` only, see http://react-component.github.io/editor-mention/examples/defaultValue.html ');
    }
    if (props.value !== undefined) {
      _this.controlledMode = true;
    }
    return _this;
  }

  Mention.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
    var suggestions = nextProps.suggestions;
    var selection = this.state.selection;

    var value = nextProps.value;
    if (value && selection) {
      value = EditorState.acceptSelection(EditorState.createWithContent(value, this._decorator), selection);
    }
    this.setState({
      suggestions: suggestions,
      value: value
    });
  };

  Mention.prototype.getPrefix = function getPrefix() {
    var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props;

    return Array.isArray(props.prefix) ? props.prefix : [props.prefix];
  };

  Mention.prototype.render = function render() {
    var _classnames,
        _this2 = this;

    var _props = this.props,
        prefixCls = _props.prefixCls,
        style = _props.style,
        tag = _props.tag,
        multiLines = _props.multiLines,
        editorKey = _props.editorKey,
        suggestionStyle = _props.suggestionStyle,
        placeholder = _props.placeholder,
        defaultValue = _props.defaultValue,
        className = _props.className,
        notFoundContent = _props.notFoundContent,
        getSuggestionContainer = _props.getSuggestionContainer,
        readOnly = _props.readOnly,
        disabled = _props.disabled,
        placement = _props.placement,
        mode = _props.mode;
    var suggestions = this.state.suggestions;
    var Suggestions = this.Suggestions;

    var editorClass = classnames(className, (_classnames = {}, _classnames[prefixCls + '-wrapper'] = true, _classnames.readonly = readOnly, _classnames.disabled = disabled, _classnames.multilines = multiLines, _classnames));
    var editorProps = this.controlledMode ? { value: this.state.value } : {};
    var defaultValueState = defaultValue && EditorState.createWithContent(typeof defaultValue === 'string' ? ContentState.createFromText(defaultValue) : defaultValue, this._decorator);
    return React.createElement(
      'div',
      { className: editorClass, style: style, ref: function ref(wrapper) {
          return _this2._wrapper = wrapper;
        } },
      React.createElement(
        EditorCore,
        _extends({
          ref: function ref(editor) {
            return _this2._editor = editor;
          },
          prefixCls: prefixCls,
          style: style,
          multiLines: multiLines,
          editorKey: editorKey,
          plugins: this.plugins,
          defaultValue: defaultValueState,
          placeholder: placeholder,
          onFocus: this.onFocus,
          onBlur: this.onBlur,
          onKeyDown: this.onKeyDown,
          onChange: this.onEditorChange
        }, editorProps, {
          readOnly: readOnly || disabled
        }),
        React.createElement(Suggestions, {
          mode: tag ? 'immutable' : mode,
          prefix: this.getPrefix(),
          prefixCls: prefixCls,
          style: suggestionStyle,
          placement: placement,
          notFoundContent: notFoundContent,
          suggestions: suggestions,
          getSuggestionContainer: getSuggestionContainer ? function () {
            return getSuggestionContainer(_this2._wrapper);
          } : null,
          onSearchChange: this.props.onSearchChange,
          onSelect: this.props.onSelect,
          noRedup: this.props.noRedup
        })
      )
    );
  };

  return Mention;
}(React.Component)
Example #6
Source File: EditorUtilities.spec.js    From wix-style-react with MIT License 4 votes vote down vote up
describe('EditorUtilities', () => {
  const linkEntity = {
    text: 'Test',
    url: 'http://wix.com',
  };

  let editorState;

  beforeEach(() => {
    editorState = EditorState.createEmpty();
  });

  describe('hasStyle', () => {
    it('should return true when editor contains a style', () => {
      const newEditorState = EditorUtilities.toggleStyle(
        editorState,
        inlineStyleTypes.bold,
      );

      expect(
        EditorUtilities.hasStyle(newEditorState, inlineStyleTypes.bold),
      ).toBe(true);
    });

    it(`should return false when editor contains a style but the selection does not`, () => {
      let newEditorState = EditorUtilities.toggleStyle(
        editorState,
        inlineStyleTypes.bold,
      );

      newEditorState = EditorState.moveSelectionToEnd(editorState);

      expect(
        EditorUtilities.hasStyle(newEditorState, inlineStyleTypes.bold),
      ).toBe(false);
    });
  });

  describe('hasBlockType', () => {
    it('should return true when editor contains a block type', () => {
      const newEditorState = EditorUtilities.toggleBlockType(
        editorState,
        blockTypes.bulletedList,
      );

      expect(
        EditorUtilities.hasBlockType(newEditorState, blockTypes.bulletedList),
      ).toBe(true);
    });

    it(`should return false when editor contains a block type but the selection does not`, () => {
      let newEditorState = EditorUtilities.toggleBlockType(
        editorState,
        inlineStyleTypes.bulletedList,
      );

      newEditorState = EditorState.moveSelectionToEnd(editorState);

      expect(
        EditorUtilities.hasBlockType(newEditorState, blockTypes.bulletedList),
      ).toBe(false);
    });
  });

  describe('hasEntity', () => {
    it('should return true when editor contains an entity', () => {
      const newEditorState = EditorUtilities.toggleLink(
        editorState,
        linkEntity,
      );

      expect(EditorUtilities.hasEntity(newEditorState, entityTypes.link)).toBe(
        true,
      );
    });

    it(`should return false when editor contains an entity but the selection does not`, () => {
      let newEditorState = EditorUtilities.toggleLink(editorState, linkEntity);

      newEditorState = EditorState.moveSelectionToEnd(editorState);

      expect(EditorUtilities.hasEntity(newEditorState, entityTypes.link)).toBe(
        false,
      );
    });
  });

  it('should attach the specified style to a block', () => {
    const newEditorState = EditorUtilities.toggleStyle(
      editorState,
      inlineStyleTypes.italic,
    );

    expect(
      EditorUtilities.hasStyle(newEditorState, inlineStyleTypes.italic),
    ).toBe(true);
  });

  it('should attach the specified type to a block', () => {
    const newEditorState = EditorUtilities.toggleBlockType(
      editorState,
      blockTypes.numberedList,
    );

    expect(
      EditorUtilities.hasBlockType(newEditorState, blockTypes.numberedList),
    ).toBe(true);
  });

  describe('toggleLink', () => {
    it('should attach the specified entity to a block', () => {
      const newEditorState = EditorUtilities.toggleLink(
        editorState,
        linkEntity,
      );

      expect(EditorUtilities.hasEntity(newEditorState, entityTypes.link)).toBe(
        true,
      );
    });

    it('should insert the text of the specified entity to a block', () => {
      const initialText = editorState.getCurrentContent().getPlainText();

      const newEditorState = EditorUtilities.toggleLink(
        editorState,
        linkEntity,
      );
      const currentText = newEditorState.getCurrentContent().getPlainText();

      expect(initialText).toEqual('');
      expect(currentText).toEqual(linkEntity.text);
    });
  });

  describe('getSelectedText', () => {
    it('should be empty when no text is selected', () => {
      expect(EditorUtilities.getSelectedText(editorState)).toEqual('');
    });

    it('should return the selected text', () => {
      const expectedText = 'Test2';
      editorState = EditorState.createWithContent(
        ContentState.createFromText(`Test1\n${expectedText}\nTest3`),
      );
      const middleBlock = editorState.getCurrentContent().getBlocksAsArray()[1];
      const anchorOffset = editorState.getSelection().getStartOffset();

      const newEditorState = EditorState.acceptSelection(
        editorState,
        new SelectionState({
          anchorOffset,
          anchorKey: middleBlock.getKey(),
          focusOffset: anchorOffset + middleBlock.getText().length,
          focusKey: middleBlock.getKey(),
        }),
      );

      expect(EditorUtilities.getSelectedText(newEditorState)).toEqual(
        expectedText,
      );
    });
  });
});