window.getSelection().getRangeAt(0) innerHTML 不破坏节点

window.getSelection().getRangeAt(0) innerHTML without breaking nodes

我正在开发一个 JavaScript 扩展,它应该以某种方式包装选定的文本并将其发送到我的服务器。完成 "wrapping" 以便服务器可以识别突出显示文本的确切位置,即使存在重复。

我按照这个 link、How to change CSS of selected text using Google Chrome Extension, to be able to obtain the selected text. Afterwards I followed this approach, How to get selected html text with javascript?,特别是选择的答案,获得了 innerHTML。 The problem is that when the selection is across different divs, it breaks the DOM, or just as zyklus said in that answer "WILL have side effects from breaking nodes in half and creating an extra span".

例如,

    <div id="IntroDiv">
        <p>
            <img src="http://localhost:9000/Theme/Images/Intro/logo.png">
            <br><br>
            A neat th<f5e975aa551d1ae4e91e8ce9><div id="IntroDiv"><p>eme for start-ups and small corporations.
        </p>
    </div>

    <div id="ProjectsSlider">
        <div id="ProjectsSliderContent">

            <p class="Title">Projects</p>
            <p class="Subtitle">Samples O</p></div></div></f5e975aa551d1ae4e91e8ce9>eme for start-ups and small corporations.
        </p>
    </div>

    <div id="ProjectsSlider">
        <div id="ProjectsSliderContent">

            <p class="Title">Projects</p>
            <p class="Subtitle">Samples Of Our Work</p>

            <div id="SliderContainer">
                <div class="LeftArrow"></div>
                <div class="RightArrow"></div>
                <div class="ThreeD swiper-container stop-swiping">
                    <div class="swiper-wrapper swiper-no-swiping" style="width: 2365px; height: 285px; transform: translate3d(-430px, 0px, 0px); -webkit-transform: translate3d(-430px, 0px, 0px); transition-duration: 0s; -webkit-transition-duration: 0s;"><div class="swiper-slide swiper-slide-duplicate" style="width: 215px; height: 285px; transition-duration: 0ms; -webkit-transition-duration: 0ms; transform: translate3d(0px, 0px, -336px) rotateX(0deg) rotateY(-75deg); -webkit-transform: translate3d(0px, 0px, -336px) rotateX(0deg) rotateY(-75deg); z-index: -2; background-image: url(http://placehold.it/215x270/);">Project 3</div><div class="swiper-slide swiper-slide-duplicate" style="width: 215px; height: 285px; transition-duration: 0ms; -webkit-transition-duration: 0ms; transform: translate3d(0px, 0px, -224px) rotateX(0deg) rotateY(-50deg); -webkit-transform: translate3d(0px, 0px, -224px) rotateX(0deg) rotateY(-50deg); z-index: -1; background-image: url(http://placehold.it/215x270/);">Project 4</div><div class="swiper-slide swiper-slide-duplicate swiper-slide-visible swiper-slide-active" style="width: 215px; height: 285px; transition-duration: 0ms; -webkit-transition-duration: 0ms; transform: translate3d(0px, 0px, -112px) rotateX(0deg) rotateY(-25deg); -webkit-transform: translate3d(0px, 0px, -112px) rotateX(0deg) rotateY(-25deg); z-index: 0; background-image: url(http://placehold.it/215x270/);">Project 5</div> <!-- Add your slides here. You're free to have different styles or content -->
                        <div class="swiper-slide swiper-slide-visible" style="width: 215px; height: 285px; transition-duration: 0ms; -webkit-transition-duration: 0ms; transform: translate3d(0px, 0px, 0px) rotateX(0deg) rotateY(0deg); -webkit-transform: translate3d(0px, 0px, 0px) rotateX(0deg) rotateY(0deg); z-index: 1; background-image: url(http://placehold.it/215x270/);">Project 1</div>
                        <div class="swiper-slide swiper-slide-visible" style="width: 215px; height: 285px; transition-duration: 0ms; -webkit-transition-duration: 0ms; transform: translate3d(0px, 0px, -112px) rotateX(0deg) rotateY(25deg); -webkit-transform: translate3d(0px, 0px, -112px) rotateX(0deg) rotateY(25deg); z-index: 0; background-image: url(http://placehold.it/215x270/);">Project 2</div>
                        <div class="swiper-slide" style="width: 215px; height: 285px; transition-duration: 0ms; -webkit-transition-duration: 0ms; transform: translate3d(0px, 0px, -224px) rotateX(0deg) rotateY(50deg); -webkit-transform: translate3d(0px, 0px, -224px) rotateX(0deg) rotateY(50deg); z-index: -1; background-image: url(http://placehold.it/215x270/);">Project 3</div>
                        <div class="swiper-slide" style="width: 215px; height: 285px; transition-duration: 0ms; -webkit-transition-duration: 0ms; transform: translate3d(0px, 0px, -336px) rotateX(0deg) rotateY(75deg); -webkit-transform: translate3d(0px, 0px, -336px) rotateX(0deg) rotateY(75deg); z-index: -2; background-image: url(http://placehold.it/215x270/);">Project 4</div>
                        <div class="swiper-slide" style="width: 215px; height: 285px; transition-duration: 0ms; -webkit-transition-duration: 0ms; transform: translate3d(0px, 0px, -448px) rotateX(0deg) rotateY(100deg); -webkit-transform: translate3d(0px, 0px, -448px) rotateX(0deg) rotateY(100deg); z-index: -3; background-image: url(http://placehold.it/215x270/);">Project 5</div>
                    <div class="swiper-slide swiper-slide-duplicate" style="width: 215px; height: 285px; transition-duration: 0ms; -webkit-transition-duration: 0ms; transform: translate3d(0px, 0px, -560px) rotateX(0deg) rotateY(125deg); -webkit-transform: translate3d(0px, 0px, -560px) rotateX(0deg) rotateY(125deg); z-index: -4; background-image: url(http://placehold.it/215x270/);">Project 1</div><div class="swiper-slide swiper-slide-duplicate" style="width: 215px; height: 285px; transition-duration: 0ms; -webkit-transition-duration: 0ms; transform: translate3d(0px, 0px, -672px) rotateX(0deg) rotateY(150deg); -webkit-transform: translate3d(0px, 0px, -672px) rotateX(0deg) rotateY(150deg); z-index: -5; background-image: url(http://placehold.it/215x270/);">Project 2</div><div class="swiper-slide swiper-slide-duplicate" style="width: 215px; height: 285px; transition-duration: 0ms; -webkit-transition-duration: 0ms; transform: translate3d(0px, 0px, -784px) rotateX(0deg) rotateY(175deg); -webkit-transform: translate3d(0px, 0px, -784px) rotateX(0deg) rotateY(175deg); z-index: -6; background-image: url(http://placehold.it/215x270/);">Project 3</div></div>

                    <div class="SeePhotos"></div>
                </div>
            </div>

            <ul id="ThreeDSwiperBullets"><li id="0" class="active"></li><li id="1"></li><li id="2"></li><li id="3"></li><li id="4"></li></ul> <!-- Where slider bullets are automatically added according to the slider by JavaScript, Index.js file -->
        </div>
    </div>

我在这里使用 f5e975aa551d1ae4e91e8ce9 来标识文本,就像通常网页中很可能不存在的任何一种独特文本一样。正如您在上面看到的,"IntroDiv" 和 "ProjectsSlider" 一样出现了两次。这是调用任何函数之前页面的同一部分。

    <div id="IntroDiv">
        <p>
            <img src="Theme/Images/Intro/logo.png">
            <br/><br/>
            A neat theme for start-ups and small corporations.
        </p>
    </div>

    <div id="ProjectsSlider">
        <div id="ProjectsSliderContent">

            <p class="Title">Projects</p>
            <p class="Subtitle">Samples Of Our Work</p>

            <div id="SliderContainer">
                <div class="LeftArrow"></div>
                <div class="RightArrow"></div>
                <div class="ThreeD swiper-container stop-swiping">
                    <div class="swiper-wrapper swiper-no-swiping">  <!-- Add your slides here. You're free to have different styles or content -->
                        <div class="swiper-slide" style="background-image:url('http://placehold.it/215x270/');">Project 1</div>
                        <div class="swiper-slide" style="background-image:url('http://placehold.it/215x270/');">Project 2</div>
                        <div class="swiper-slide" style="background-image:url('http://placehold.it/215x270/');">Project 3</div>
                        <div class="swiper-slide" style="background-image:url('http://placehold.it/215x270/');">Project 4</div>
                        <div class="swiper-slide" style="background-image:url('http://placehold.it/215x270/');">Project 5</div>
                    </div>

                    <div class="SeePhotos"></div>
                </div>
            </div>

            <ul id="ThreeDSwiperBullets"></ul> <!-- Where slider bullets are automatically added according to the slider by JavaScript, Index.js file -->
        </div>
    </div>

这是我的代码。

//save_last_element.js    
document.body.addEventListener('contextmenu', function(e) {
    LAST_SELECTION = window.getSelection().getRangeAt(0);
}, false);


//script.js
if (LAST_SELECTION) {
    var mySelection = LAST_SELECTION.cloneRange();

    var selectionContents = mySelection.cloneContents();
    var div = document.createElement("f5e975aa551d1ae4e91e8ce9");
    div.appendChild(selectionContents);
    mySelection.insertNode(div);
}

有没有办法避免弄乱 DOM?我可以通过完全不同的方法以某种方式识别所选文本的位置吗?

要提取所选文本,您可以仅遍历文本节点的选择并将它们连接起来。

var content = window.getSelection().getRangeAt(0).cloneContents();
var treeWalker = document.createTreeWalker(content, NodeFilter.SHOW_TEXT);
var text = '';

while (treeWalker.nextNode()) { 
    text = text.concat(treeWalker.currentNode.nodeValue);
}
console.log(text);

编辑

如何用标识符字符串包装选择:

String.prototype.splice = function( idx, rem, s ) {
    return (this.slice(0,idx) + s + this.slice(idx + Math.abs(rem)));
};

var range = window.getSelection().getRangeAt(0);
range.startContainer.nodeValue = range.startContainer.nodeValue.splice(range.startOffset, 0, '[highlight]');
range.endContainer.nodeValue = range.endContainer.nodeValue.splice(range.endOffset, 0, '[/highlight]');

splicethis post

提供

所以,经过多次尝试,我可以做到。

    var myAnchorNodeValue = window.getSelection().anchorNode.nodeValue;
    var myAnchorOffset = window.getSelection().anchorOffset
    var myFocusOffset =  window.getSelection().focusOffset

    var myFocusNodeLength = window.getSelection().focusNode.nodeValue.length;

    window.getSelection().anchorNode.nodeValue = myAnchorNodeValue.slice(0, myAnchorOffset) + "[IDENTIFY]" + myAnchorNodeValue.slice(myAnchorOffset);

    var myFocusNodeValue = window.getSelection().focusNode.nodeValue;

    if(window.getSelection().focusNode.nodeValue.length - myFocusNodeLength > 0) {
        myFocusOffset += window.getSelection().focusNode.nodeValue.length - myFocusNodeLength;
    }

    window.getSelection().focusNode.nodeValue = myFocusNodeValue.slice(0, myFocusOffset) + "[/IDENTIFY]" + myFocusNodeValue.slice(myFocusOffset);

    LAST_SELECTION = window.getSelection().getRangeAt(0);
    myDocument = document.documentElement.innerHTML;

效果很好。