【问题标题】:window.getSelection().getRangeAt(0) innerHTML without breaking nodeswindow.getSelection().getRangeAt(0) innerHTML 不破坏节点
【发布时间】:2015-01-27 14:50:23
【问题描述】:

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

我点击了这个链接,How to change CSS of selected text using Google Chrome Extension,以获得选定的文本。之后我按照这种方法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?我可以通过完全不同的方法以某种方式识别所选文本的位置吗?

【问题讨论】:

    标签: javascript dom


    【解决方案1】:

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

        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;
    

    效果很好。

    【讨论】:

    【解决方案2】:

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

    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 友情提供

    【讨论】:

    • 再次,“整个问题在于识别 DOM 中的文本。使用纯文本方法,如果用户选择了在 DOM 中多次出现的单词,我想识别那个他实际上选择了,而且没有选错,也不是全部。”
    • 现在我真的不明白。这个只会提取选择中的所有文本,而不是 DOM 中的所有文本。 “一个词是否多次在 DOM(或选择)中”与选择没有任何关系,恕我直言。
    • 嗯,重点是我需要将整个 DOM 发送到服务器。它应该为所选文本添加背景/边框/或其他内容并托管整个 MHTML 页面。现在发送 MHTML 页面是可行的,唯一的问题是确定所选文本本身的位置,以便我可以按照我想要的方式设置它的样式。对不起,有点混乱。
    • 标识包装器是否必须是 DOM 节点?否则,您只能使用字符串标识符。与此同时,我会想办法用实际节点包装选定的文本/节点。
    • 不,不必如此。 “字符串标识符”到底是什么意思?
    猜你喜欢
    • 2012-06-25
    • 1970-01-01
    • 1970-01-01
    • 2013-11-13
    • 2011-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-14
    相关资源
    最近更新 更多