Ermia
Ermia

Reputation: 21

How Can I get the start position and end position of selected text in contenteditable?

This question is very important for me.

I have this element:

<div class="title">
    Hello Every thig is<span style="font-family: Tahoma;font-size: 20px">Good ! </span>
</div>

How can I get the start position and the end position of the selected text?

This is my code. It works when the parent element does not have any child.

    var selectedRange = window.getSelection().getRangeAt(0);
    var selectedNode = selectedRange.commonAncestorContainer;
    console.log("selected node: ", selectedNode);
    console.log(selectedRange.anchorNode)
    console.log("selected node value: ", selectedNode.nodeValue);
    console.log("selection chars range: START POS: ", selectedRange.startOffset);
    console.log("selection chars range: END POS: ", selectedRange.endOffset);

Thanks for your help.

Upvotes: 2

Views: 913

Answers (1)

Bob Dust
Bob Dust

Reputation: 2460

Oh dear, range handling's been always the pain in the ... head! Try this (tested with Chrome):

        var selection = function () {
            var selectedRange = window.getSelection().getRangeAt(0);
            if(selectedRange)
            {
                var sc = selectedRange.startContainer,
                so = selectedRange.startOffset,
                ec = selectedRange.endContainer,
                eo = selectedRange.endOffset;
                var editable = document.getElementById('editor');
                var start = rootOffset(editable, { node: sc, offset: so });
                var end = rootOffset(editable, { node: ec, offset: eo });
                console.log(start.offset);
                console.log(end.offset);
            }
        };

        var rootOffset = function (root, point) {
            if (point.node === root)
            {
                return point;
            }
            var previousSibling = point.node.previousSibling;
            if (previousSibling) {
                return {
                    node: point.node,
                    offset: rootOffset(root, {
                        node: previousSibling,
                        offset: nodeLength(previousSibling)
                    }).offset + point.offset
                };
            }
            else
            {
                var parentNode = point.node.parentNode;
                if(parentNode)
                {
                    return rootOffset(root, { node: parentNode, offset: point.offset });
                }
            }
            return point;
        };

        var isText = function (node) {
            return node && node.nodeType === 3;
        };

        var nodeLength = function (node) {
            if (isText(node)) {
                return node.nodeValue.trim().length;
            }
            var length = 0;
            var childNodes = node.childNodes;
            if (childNodes)
            {
                for(var i = 0; i < childNodes.length; i++)
                {
                    length += nodeLength(childNodes[i]);
                }
            }
            return length;
        };
    <div id="editor" contenteditable="true">
        <div class="title">Hello Every thing is<span style="font-family: Tahoma;font-size: 20px">Good ! </span>
        </div>
    </div>
    <button type="button" id="btnLog" onclick="selection();">Log Selection</button>

Upvotes: 1

Related Questions