jpuri / draftjs-utils

An collection of useful utility functions for DraftJS.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

text-align not persisted on new lines

kwarr128 opened this issue · comments

I notice that the text-align attributes (really, anything in the "data" object of a block, but i dont think you are using it here for anything other than text-align) are not carried over to new blocks when hitting the enter key to create a new line. If i'm currently right aligned with my text, I would expect that alignment to continue when hitting the enter key for a new line (this is how bold, underline, lists, etc behave).

I found this issue on draftjs facebookarchive/draft-js#723 that suggests some workarounds that can be done for persisting things in the "data" object when splitting a block. Maybe something similar can be done here in the insertNewUnstyledBlock function https://github.com/jpuri/draftjs-utils/blob/master/js/block.js#L169 (though the name of the function might not make sense anymore if it were to persist styling from the current block)

That is very good point @kwarr128. I will consider doing it - though I am not sure how soon I can get to it coz of other priorities.
Thx :)

@jpuri I could potentially work on it in a few weeks if you haven't gotten to it by then (and if you're open to a PR for it). I wanted to make sure this is something you'd want first. (my other option being to maintain a fork, but i'd rather contribute back if you think its a good idea)

It definitely good idea, I will be happy to have a PR for this.

@jpuri So I finally had time to look into this some more. It turns out I didn't fully understand what was going on at first. Your handleNewLine function only does anything if you are doing a soft line break, or doing a normal line break for a block type that isnt 'unstyled' (with the exception of the list types special cases) in order to just reset the new block type to 'unstyled'. Otherwise, it just returns undefined and lets the draftjs default handling kick in. Maintaining the data properties when resetting block type is arguable, I'm not really sure if it makes sense or not. I'm leaning towards not.

My use case is my own editor (not using your react-draft-wisywig directly, but being inspired by it, and still using this helper library), so i was able to fix my problem myself in my editor's handleReturn function like this:

  handleReturn = event => {
    const { editorState } = this.state;

    // Your handleNewLine function imported from this package
    const newEditorState = handleNewLine(editorState, event);
    if (newEditorState) {
      this.onChange(newEditorState);
      return true;
    }

    // Maintain content of the "data" property of the current block when splitting to create the
    // new block (instead of draftjs normal behavior of not maintaining any part of data).
    // This is adapted from https://github.com/facebook/draft-js/issues/723#issuecomment-367918580
    const contentState = editorState.getCurrentContent();
    const selection = editorState.getSelection();
    const startKey = selection.getStartKey();
    const currentBlock = contentState.getBlockForKey(startKey);
    if (currentBlock) {
      const blockData = currentBlock.getData();
      if (blockData) {
        const newContentState = Modifier.splitBlock(contentState, selection);
        const splitState = EditorState.push(
          editorState,
          newContentState,
          'split-block'
        );
        const splitStateWithData = Modifier.mergeBlockData(
          splitState.getCurrentContent(),
          splitState.getSelection(),
          blockData
        );
        const finalState = EditorState.push(
          editorState,
          splitStateWithData,
          'split-block'
        );
        this.onChange(finalState);
        return true;
      }
    }
    return false;
  }

@kwarr128 : thanks its useful for me, let me wait and see. If more users complain about this, I will add this fix to repo also.

Handler provided by @kwarr128 works great for me. My case is the same: bare draftjs and my own logic. Thanks!

Looks like @kwarr128's solution works over here too (a year and a half later). I do think this should be default behavior!

FYI, I opted for a slightly more hacky approach, but requires me to maintain less code:

/**
 * Replacement react-draft-wysiwyg handleReturn method, where we override the
 * default new line functionality.
 *
 * @since  5.15.27
 *
 * @param  {Object} event The event object.
 *
 * @return {bool}
 */
handleReturn = event => {

	// draftjs-utils handleNewLine will keep prior block properties
	// with a shift + enter. That is the default functionality we want,
	// so we give it a fake event where getModifierState( 'Shift' )
	// always returns true, giving us the desired behavior.
	const fakeEvent = {
		which: event.which,
		getModifierState: key => 'Shift' === key ? true : event.getModifierState('Shift'),
	};

	// Your handleNewLine function imported from this package
	const editorState = handleNewLine(this.state.editorState, fakeEvent);
	if (editorState) {
		this.onEditorChange(editorState);
		return true;
	}

	return false;
};

@jpuri So I finally had time to look into this some more. It turns out I didn't fully understand what was going on at first. Your handleNewLine function only does anything if you are doing a soft line break, or doing a normal line break for a block type that isnt 'unstyled' (with the exception of the list types special cases) in order to just reset the new block type to 'unstyled'. Otherwise, it just returns undefined and lets the draftjs default handling kick in. Maintaining the data properties when resetting block type is arguable, I'm not really sure if it makes sense or not. I'm leaning towards not.

My use case is my own editor (not using your react-draft-wisywig directly, but being inspired by it, and still using this helper library), so i was able to fix my problem myself in my editor's handleReturn function like this:

  handleReturn = event => {
    const { editorState } = this.state;

    // Your handleNewLine function imported from this package
    const newEditorState = handleNewLine(editorState, event);
    if (newEditorState) {
      this.onChange(newEditorState);
      return true;
    }

    // Maintain content of the "data" property of the current block when splitting to create the
    // new block (instead of draftjs normal behavior of not maintaining any part of data).
    // This is adapted from https://github.com/facebook/draft-js/issues/723#issuecomment-367918580
    const contentState = editorState.getCurrentContent();
    const selection = editorState.getSelection();
    const startKey = selection.getStartKey();
    const currentBlock = contentState.getBlockForKey(startKey);
    if (currentBlock) {
      const blockData = currentBlock.getData();
      if (blockData) {
        const newContentState = Modifier.splitBlock(contentState, selection);
        const splitState = EditorState.push(
          editorState,
          newContentState,
          'split-block'
        );
        const splitStateWithData = Modifier.mergeBlockData(
          splitState.getCurrentContent(),
          splitState.getSelection(),
          blockData
        );
        const finalState = EditorState.push(
          editorState,
          splitStateWithData,
          'split-block'
        );
        this.onChange(finalState);
        return true;
      }
    }
    return false;
  }

code works perfectly but there's one issue with it, when i hit space i preserve alignment, but the cursor is gone, but if i type any symbol it appears again, but if i delete symbol from that line cursor is gone again, so apparently if it's an empty string there will be no cursor blinking on this line, which is weird)

although when i'm not using any alignment everything is working correctly (i mean a cursor)

so can i force selection on this line somehow? this should solve another my issue, when hitting enter like a dozens of type and start typing it jumps right into that line, and i want to have that exact line to be visible, like for example here in github editor, no matter how many enters you hit you will always be on the right line

upd: it appears that cursor dissapearing even if i just click on any of the "align" buttons, if row is empty

@jpuri or @kwarr128 pls can you help?