Skip to content

Instantly share code, notes, and snippets.

@karudo
Created May 15, 2020 17:41
Show Gist options
  • Select an option

  • Save karudo/af9cdafcb0890076d804965e11a64a36 to your computer and use it in GitHub Desktop.

Select an option

Save karudo/af9cdafcb0890076d804965e11a64a36 to your computer and use it in GitHub Desktop.

Revisions

  1. karudo created this gist May 15, 2020.
    108 changes: 108 additions & 0 deletions draftutils.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,108 @@
    import {
    EditorState,
    ContentBlock,
    genKey
    } from 'draft-js';

    import { List, Map } from 'immutable';

    export const getSelectionRange = () => {
    const selection = window.getSelection();
    if (selection.rangeCount === 0) return null;
    return selection.getRangeAt(0);
    };

    export const getSelectionCoords = (selectionRange) => {
    const editorBounds = document.getElementById('editor-container').getBoundingClientRect();
    const rangeBounds = selectionRange.getBoundingClientRect();
    const rangeWidth = rangeBounds.right - rangeBounds.left;
    const offsetLeft = (rangeBounds.left - editorBounds.left)
    + (rangeWidth / 2)
    /* 107px is width of inline toolbar */
    - (142 / 2);
    // 42px is height of inline toolbar (35px) + 5px center triangle and 2px for spacing
    const offsetTop = rangeBounds.top - editorBounds.top - 42;

    return { offsetLeft, offsetTop };
    };

    export const getCurrentBlock = (editorState) => {
    const selectionState = editorState.getSelection();
    const contentState = editorState.getCurrentContent();

    return contentState.getBlockForKey(selectionState.getStartKey());
    };

    /*
    Used from [react-rte](https://github.com/sstur/react-rte/blob/master/src/lib/insertBlockAfter.js)
    by [sstur](https://github.com/sstur)
    */
    export const addNewBlockAt = (
    editorState,
    pivotBlockKey,
    newBlockType = 'unstyled',
    initialData = new Map({})
    ) => {
    const content = editorState.getCurrentContent();
    const blockMap = content.getBlockMap();
    const block = blockMap.get(pivotBlockKey);

    if (!block) {
    throw new Error(`The pivot key - ${ pivotBlockKey } is not present in blockMap.`);
    }

    const blocksBefore = blockMap.toSeq().takeUntil((v) => (v === block));
    const blocksAfter = blockMap.toSeq().skipUntil((v) => (v === block)).rest();
    const newBlockKey = genKey();

    const newBlock = new ContentBlock({
    key: newBlockKey,
    type: newBlockType,
    text: '',
    characterList: new List(),
    depth: 0,
    data: initialData,
    });

    const newBlockMap = blocksBefore.concat(
    [[pivotBlockKey, block], [newBlockKey, newBlock]],
    blocksAfter
    ).toOrderedMap();

    const selection = editorState.getSelection();

    const newContent = content.merge({
    blockMap: newBlockMap,
    selectionBefore: selection,
    selectionAfter: selection.merge({
    anchorKey: newBlockKey,
    anchorOffset: 0,
    focusKey: newBlockKey,
    focusOffset: 0,
    isBackward: false,
    }),
    });

    return EditorState.push(editorState, newContent, 'split-block');
    };

    export const closest = (element, matchFunction) => {
    let currentElement = element;

    while (currentElement) {
    if (matchFunction(currentElement)) return currentElement;
    currentElement = currentElement.parentNode;
    }
    };

    export const hasClass = (element, className) => {
    let isHasClass = false;

    if (element.classList) {
    isHasClass = element.classList.contains(className);
    } else {
    isHasClass = new RegExp(`(^| )${ className }( |$)`, 'gi').test(element.className);
    }

    return isHasClass;
    };