wahanegi/vibereport

View on GitHub
app/javascript/components/UI/rich-text/cursor.js

Summary

Maintainability
D
1 day
Test Coverage
//For set up caret to the defiantly position

import RichText from "./rich-text";
export default class Cursor {
    static getCurrentCursorPosition(parentElement, initCoord = {x: 0, y: 0}) {
        if(window.getSelection()) {
            const selection = window.getSelection()
            let charCount = -1
            let focusNode = null
            let node = null
            let focusOffset = null
            let realPos = 0
            let realFocusOffset
            let coordinates = initCoord;
            if (selection.focusNode) {
                if (Cursor._isChildOf(selection.focusNode, parentElement)) {
                    focusNode = selection.focusNode;
                    node = focusNode;
                    focusOffset = selection.focusOffset
                    charCount = focusOffset;
                    realPos += focusNode.parentNode.tagName === 'SPAN' ?
                        focusNode.parentNode.outerHTML.length - '</span>'.length -
                        RichText.encodeSpace(RichText.decodeSpace160(focusNode.textContent)).length : 0
                    realFocusOffset = RichText.encodeSpace(RichText.decodeSpace160(focusNode.textContent.slice(0, focusOffset))).length
                    while (node) {
                        if (node === parentElement) {
                            break;
                        }
                        if (node.previousSibling) {
                            node = node.previousSibling;
                            charCount += node.textContent.length;
                            realPos +=
                                (node.outerHTML === undefined ? RichText.encodeSpace(RichText.decodeSpace160(node.textContent)) : node.outerHTML).length
                        } else {
                            node = node.parentNode;
                            if (node === null) {
                                break;
                            }
                        }
                    }
                }
            }
            if (selection.rangeCount) {
                let range = selection.getRangeAt(0).cloneRange();
                if (range.getClientRects) {
                    range.collapse(true);
                    let rects = range.getClientRects();
                    if (rects.length > 0) {
                        let rect = rects[0];
                        coordinates.x = rect.left + window.scrollX ;
                        coordinates.y = rect.top + window.scrollY ;
                    }
                }
            }
            return {
                charCount: charCount,
                focusNode: focusNode,
                focusOffset: focusOffset,
                realPos: realPos + realFocusOffset,
                realFocusOffset: realFocusOffset,
                isDIV: focusNode !== null ? focusNode.parentNode.tagName === 'DIV' : false,
                isSPAN: focusNode !== null ? focusNode.parentNode.className === 'color-primary'  : false,
                coordinates
            }
        }
    }

    static setCurrentCursorPosition(chars, element) {
        if (chars >= 0) {
            const selection = window.getSelection();
            let range = Cursor._createRange(element, { count: chars });
            if (range) {
                range.collapse(false);
                selection.removeAllRanges();
                selection.addRange(range);
            }
        }
    }

    static _createRange(node, chars, range) {
        if (!range) {
            range = document.createRange()
            range.selectNode(node);
            range.setStart(node, 0);
        }
        if (chars.count === 0) {
            range.setEnd(node, chars.count);
        } else if (node && chars.count >0) {
            if (node.nodeType === Node.TEXT_NODE) {
                if (node.textContent.length < chars.count) {
                    chars.count -= node.textContent.length;
                } else {
                    range.setEnd(node, chars.count);
                    chars.count = 0;
                }
            } else {
                for (let lp = 0; lp < node.childNodes.length; lp++) {
                    range = Cursor._createRange(node.childNodes[lp], chars, range);
                    if (chars.count === 0) {
                        break;
                    }
                }
            }
        }
        return range;
    }

    static _isChildOf(node, parentElement) {
        while (node !== null) {
            if (node === parentElement) {
                return true;
            }
            node = node.parentNode;
        }
        return false;
    }
}