【问题标题】:Replace selected text in Firefox替换 Firefox 中的选定文本
【发布时间】:2010-01-09 11:58:38
【问题描述】:

如何在 Firefox 中使用 PURE javascript 将所选文本替换为另一个文本?

这是我用来获取选择的:

var sel = this.getSelection();
var range = sel.getRangeAt(0);

还有这个重要的问题:
我想保留字符的原始格式(当然新字符串会有正确的格式)
选择可以“跨元素”完成(我的意思是选择可以包含来自一个元素(如 div 或 table)的一些文本以及来自另一个元素的一些文本)。

例如,文档:

<div>
 this is a test
</div>
<div>
<b>still a test</b>
</div>
 <table style="width:100%;">
        <tr>
            <td>
                another word</td>
            <td>
                stackoverflow</td>
        </tr>
        <tr>
            <td>
                bump</td>
            <td>
               </td>
        </tr>
    </table>

用户选择以下文本(通过一次选择):

他是一个测试仍然是一个测试不是

所以现在我想替换保持格式的文本,例如用新字符串替换所有内容 =

XXX XX X XXXX XXXXX X XXXX XXXX

最终文档(替换后)将是:

<div>
 tXXX XX X XXXX
</div>
<div>
<b>XXXXX X XXXX</b>
</div>
 <table style="width:100%;">
        <tr>
            <td>
                XXXXher word</td>
            <td>
                stackoverflow</td>
        </tr>
        <tr>
            <td>
                bump</td>
            <td>
               </td>
        </tr>
    </table>

【问题讨论】:

    标签: javascript


    【解决方案1】:

    Wooove,这太可惜了!

    Javascript

    var sel, range, nodevalue, startFound, stop;
    
    function goThroughElements(el){
        // If el is the start node, set startFound to true
        if(el.isSameNode(range.startContainer)) startFound = true;
        
        if(startFound){
            // If this is the start node, replace the text like this: abcd[ef gh] --> abcdxx xx
            if(el.isSameNode(range.startContainer)){
                // \w stands for a word character
                nodevalue = el.nodeValue.substring(range.startOffset).replace(/\w/g, 'x');
                el.nodeValue = el.nodeValue.substring(0, range.startOffset) + nodevalue;
                
            }
    
            // If this is the end node, replace the value like this: [abc def]gh ij -> xxx xxxgh ij
            else if(el.isSameNode(range.endContainer)){
                nodevalue = el.nodeValue.substring(0,range.endOffset).replace(/\w/g, 'x');
                el.nodeValue = nodevalue + el.nodeValue.substring(range.endOffset);
                
                // Now we can stop
                stop = true;
            }
            
            // If this is just a text node, replace the value by xxxx
            else if(el.nodeType == 3){
                el.nodeValue = el.nodeValue.replace(/\w/g, 'x')
            }
        }
        
        // Loop trough el's brothers
        while(el){
            // Stop if we need to
            if(stop) return;
            
            // If this element has child nodes, call this function again with the first child node
            if(el.hasChildNodes()){
                goThroughElements(el.childNodes[0]);
            }
            
            // Jump to el's brother, or quit the loop
            if(el.nextSibling)
                el = el.nextSibling;
            else
                break;
        }
        
    }
        
    $(document).ready(function() {
        $(this).mouseup(function(){
            // Get the selection
            sel = window.getSelection();
            range = sel.getRangeAt(0);
            
            // Stop must be false if the last selected text node isn't found, startFound must be false when the start isn't found
            stop = false; startFound = false;
            
            if(range.collapsed == false){
                // Check if the selection takes place inside one text node element
                if(range.startContainer.isSameNode(range.endContainer)){
                    // ab[cdefg]h  -> aaxxxxxh
                    nodevalue = range.startContainer.nodeValue;
                    range.startContainer.nodeValue = nodevalue.substring(0, range.startOffset) + nodevalue.substring(range.startOffset, range.endOffset).replace(/\w/g, 'x') + nodevalue.substring(range.endOffset);
                } else {    
                    // If the start node of the selection isn't the same as the end node, loop through all elements
                    goThroughElements(range.commonAncestorContainer.childNodes[0]);
                }
                // Collapse selection.
                range.collapse(true);
            }            
        });
    });
    

    示例

    你当然可以try the code

    也许这不是最佳解决方案,因为它从根开始搜索起始节点。从range.startContainerrange.endContainer 的第一个公共父元素开始搜索会更快,但我不知道该怎么做...

    编辑

    我将 to-X 函数包装在 if(range.collapsed == false) 中并使用 range.commonAncestorContainer.childNodes[0] 来开始迭代从选择的开始和结束位置的公共父级的第一个子级开始的元素

    【讨论】:

    • 这太棒了!对于父元素,我认为我们可以使用 range.commonAncestorContainer,并检查边界 range.compareBoundaryPoints。请看看它是否可以用于您的代码(我认为可以),无论如何,即使它是最重要的,我会在您发表评论后接受您的回答:) 谢谢
    • 我认为是 range.comparePoint 而不是 range.compareBoundaryPoints
    • 请注意,如果所选文本位于文本框内,则此方法不起作用。如果那是你想看到的:stackoverflow.com/questions/4714192/…
    猜你喜欢
    • 2011-04-27
    • 2011-04-29
    • 1970-01-01
    • 1970-01-01
    • 2011-08-02
    • 2017-07-24
    • 1970-01-01
    • 1970-01-01
    • 2012-12-21
    相关资源
    最近更新 更多