typeof programmer
typeof programmer

Reputation: 1609

How to auto-expand user selected text

I have few spans like below showed. What is want to do is auto-expand user selection based on name attribute, for example, when user select "ive i", I should auto-expand to "live in " because the heading select character 'i' share the same name attribute as leading character 'l' in the name group "2", and the tailing select character 'i' share the same name attribute as leading character ' ' in the name group "3".

<span name="1">I</span>
<span name="1"> </span>
<span name="2">l</span>
<span name="2">i</span>
<span name="2">v</span>
<span name="2">e</span>
<span name="2"> </span>
<span name="3">i</span>
<span name="3">n</span>
<span name="3"> </span>
<span name="4">m</span>
<span name="4">a</span>
<span name="4">i</span>
<span name="4">n</span>
<span name="4"> </span>
<span name="5">s</span>
<span name="5">t</span>
<span name="5">.</span>

Here is my code, my though is to find user selection first and put them in a container span, and then find the first child and last child and get their "name" attribute, then I can find the full collection of leading characters and tailing characters, finally put those two collections to the same container.

var selection = window.getSelection();

    var range = selection.getRangeAt(0);

    // If the range spans some text, and inside a tag, set its css class.
    if (range && !selection.isCollapsed) {

        var container = document.createElement("span");

        var selectionContents = range.extractContents();

        container.appendChild(selectionContents);

        var firstChildIndex = container.firstElementChild.getAttribute("name");
        var lastChildIndex = container.lastElementChild.getAttribute("name");

        var fullHeadToken = document.getElementsByName(firstChildIndex);
        var fullTailToken = document.getElementsByName(lastChildIndex);

        for (var i = 0; i < fullHeadToken.length; i++) {
            var clonedHeadSpan = fullHeadToken[i].cloneNode(true);
            container.appendChild(clonedHeadSpan);

        }

        if (firstChildIndex != lastChildIndex) {
            for (var i = 0; i < fullTailToken.length; i++) {
                var clonedTailSpan = fullTailToken[i].cloneNode(true);
                container.appendChild(clonedTailSpan);

            }
        }

        for (var i = 0; i < container.children.length; i++) {
            if (container.children[i].innerHTML == "") {
                container.children[i].remove();
            }
        }

        alert(container.innerHTML + "##");



    }

But the result is not what I want, the result is "ive i ln ". Any idea how to make the right order happen? Thanks.

Upvotes: 1

Views: 41

Answers (1)

typeof programmer
typeof programmer

Reputation: 1609

Update, I figured out how to solve this issue, here is my code:

var selectedText = "";
    var selection = window.getSelection();

    var range = selection.getRangeAt(0);

    if (range && !selection.isCollapsed) {

        var container = document.createElement("span");
        var newContainer = document.createElement("span");

        var selectionContents = range.extractContents();

        container.appendChild(selectionContents);

        var firstChildIndex = container.firstElementChild.getAttribute("name");
        var lastChildIndex = container.lastElementChild.getAttribute("name");

        var fullHeadToken = document.getElementsByName(firstChildIndex);
        var fullTailToken = document.getElementsByName(lastChildIndex);

        if (firstChildIndex != lastChildIndex) {

            for (var i = 0; i < fullHeadToken.length; i++) {
                var clonedHeadSpan = fullHeadToken[i].cloneNode(true);
                newContainer.appendChild(clonedHeadSpan);

            }

            for (var i = 0; i < container.children.length; i++) {
                if (container.children[i].innerHTML != "") {
                    var clonedSelectSpan = container.children[i]
                            .cloneNode(true);
                    newContainer.appendChild(clonedSelectSpan);
                }
            }

            for (var i = 0; i < fullTailToken.length; i++) {
                if (fullTailToken[i].innerHTML != "") {
                    var clonedTailSpan = fullTailToken[i].cloneNode(true);
                    newContainer.appendChild(clonedTailSpan);
                }
            }

        } else {
            var breakIndex;

            for (var i = 0; i < fullHeadToken.length; i++) {
                if (fullHeadToken[i].innerHTML != "") {
                    var clonedHeadSpan = fullHeadToken[i].cloneNode(true);
                    newContainer.appendChild(clonedHeadSpan);
                } else {
                    breakIndex = i;
                    break;
                }
            }

            for (var i = 0; i < container.children.length; i++) {
                if (container.children[i].innerHTML != "") {
                    var clonedSelectSpan = container.children[i]
                            .cloneNode(true);
                    newContainer.appendChild(clonedSelectSpan);
                }
            }

            for (var i = breakIndex; i < fullHeadToken.length; i++) {
                if (fullHeadToken[i].innerHTML != "") {
                    var clonedTailSpan = fullHeadToken[i].cloneNode(true);
                    newContainer.appendChild(clonedTailSpan);
                }
            }

        }

        for (var i = 0; i < newContainer.children.length; i++) {
            if (newContainer.children[i].innerHTML == "") {
                newContainer.children[i].remove();
            }
        }

        // remove existing text and expand to whole token
        for (var i = 0; i < fullHeadToken.length; i++) {
            var nodeToRemove = fullHeadToken[i];
            nodeToRemove.innerHTML = "";

        }

        if (firstChildIndex != lastChildIndex) {
            for (var i = 0; i < fullTailToken.length; i++) {
                var nodeToRemove = fullTailToken[i];
                nodeToRemove.innerHTML = "";

            }
        }


        for (var i = 0; i < newContainer.children.length; i++) {
            if (newContainer.children[i].innerHTML != "") {
                selectedText += newContainer.children[i].innerHTML;

            }
        }

        return selectedText;

    }

Upvotes: 1

Related Questions