React

by Arthur Lutkevichus

HTML

<div id="app">
x
  <TodoApp />
  x
</div>

CSS

.form-control {
  background: red;
  min-width: 10rem;
  height: auto;
  display: inline-block;
}

React

class TodoApp extends React.Component {
    constructor(props) {
        super(props);
        this.component = Symbol("SubstitutionField");

        this.uniqueId = this.component.description + "-" + (Date.now()).toString(32);
        this.varId = this.uniqueId + "-var-";

        this.state = {
            value: this.props.value || ""
        };

        this.saveCaretPosition = this.saveCaretPosition.bind(this);
        this.onChange = this.onChange.bind(this);
        //this.onMouseEnter = this.onMouseEnter.bind(this);

        this.container = document.createElement("div");
    }

    saveCaretPosition(context) {
        const selection = window.getSelection();
        if (!selection.anchorNode) {
            return {
                pos: 0,
                restore: () => {
                }
            };
        }
        const range = selection.getRangeAt(0);
        range.setStart(context, 0);
        let len = range.toString().length;

        return {
            pos: len,
            restore: forcePosition => {
                let lastNode = null;

                const treeWalker = document.createTreeWalker(context, NodeFilter.SHOW_TEXT, elem => {
                    if (len > elem.textContent.length) {
                        len -= elem.textContent.length;
                        lastNode = elem;
                        return NodeFilter.FILTER_REJECT
                    }
                    return NodeFilter.FILTER_ACCEPT;
                });
                const c = treeWalker.nextNode();
                const pos = {
                    node: c ? c : context,
                    position: c ? (_.isUndefined(forcePosition) ? len : Math.max(forcePosition, 0)) : 0
                };

                selection.removeAllRanges();
                const range = new Range();
                range.setStart(pos.node, pos.position);
                selection.addRange(range);
            }
        }
    }

    onMouseEnter(event) {
       ...