选择元素中的文本(类似于用鼠标突出显示)

时间:2009-06-12 06:35:12

标签: javascript jquery

我想让用户点击一个链接,然后在另一个元素中选择HTML文本(输入)。

通过“选择”,我的意思与通过将鼠标拖过它来选择文本的方式相同。这是一个研究的熊,因为每个人都在谈论其他术语中的“选择”或“突出”。

这可能吗?到目前为止我的代码:

HTML:

<a href="javascript:" onclick="SelectText('xhtml-code')">Select Code</a>
<code id="xhtml-code">Some Code here </code>

JS:

function SelectText(element) {
    $("#" + element).select();
}

我错过了一些明显的东西吗?

16 个答案:

答案 0 :(得分:577)

普通Javascript

function selectText(node) {
    node = document.getElementById(node);

    if (document.body.createTextRange) {
        const range = document.body.createTextRange();
        range.moveToElementText(node);
        range.select();
    } else if (window.getSelection) {
        const selection = window.getSelection();
        const range = document.createRange();
        range.selectNodeContents(node);
        selection.removeAllRanges();
        selection.addRange(range);
    } else {
        console.warn("Could not select text in node: Unsupported browser.");
    }
}

const clickable = document.querySelector('.click-me');
clickable.addEventListener('click', () => selectText('target'));
<div id="target"><p>Some text goes here!</p><p>Moar text!</p></div>
<p class="click-me">Click me!</p>

这是working demo。对于那些寻找jQuery插件的人,我做了one of those too


jQuery(原始回答)

我在this thread找到了解决方法。我能够修改给定的信息并将其与一些jQuery混合,以创建一个非常棒的函数来选择任何元素中的文本,无论浏览器如何:

function SelectText(element) {
    var text = document.getElementById(element);
    if ($.browser.msie) {
        var range = document.body.createTextRange();
        range.moveToElementText(text);
        range.select();
    } else if ($.browser.mozilla || $.browser.opera) {
        var selection = window.getSelection();
        var range = document.createRange();
        range.selectNodeContents(text);
        selection.removeAllRanges();
        selection.addRange(range);
    } else if ($.browser.safari) {
        var selection = window.getSelection();
        selection.setBaseAndExtent(text, 0, text, 1);
    }
}

答案 1 :(得分:120)

这是一个没有浏览器嗅探且不依赖于jQuery的版本:

function selectElementText(el, win) {
    win = win || window;
    var doc = win.document, sel, range;
    if (win.getSelection && doc.createRange) {
        sel = win.getSelection();
        range = doc.createRange();
        range.selectNodeContents(el);
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (doc.body.createTextRange) {
        range = doc.body.createTextRange();
        range.moveToElementText(el);
        range.select();
    }
}

selectElementText(document.getElementById("someElement"));
selectElementText(elementInIframe, iframe.contentWindow);

答案 2 :(得分:19)

Jason的代码不能用于iframe中的元素(因为范围与窗口和文档不同)。我修复了这个问题并修改了它,以便用作任何其他jQuery插件(可链接):

示例1:选择&lt;内部的所有文本。代码&gt;单击标签并添加“已选择”类:

$(function() {
    $("code").click(function() {
        $(this).selText().addClass("selected");
    });
});

示例2:单击按钮,选择Iframe中的元素:

$(function() {
    $("button").click(function() {
        $("iframe").contents().find("#selectme").selText();
    });
});

注意:请记住,iframe源应位于同一个域中,以防止出现安全错误。

jQuery插件:

jQuery.fn.selText = function() {
    var obj = this[0];
    if ($.browser.msie) {
        var range = obj.offsetParent.createTextRange();
        range.moveToElementText(obj);
        range.select();
    } else if ($.browser.mozilla || $.browser.opera) {
        var selection = obj.ownerDocument.defaultView.getSelection();
        var range = obj.ownerDocument.createRange();
        range.selectNodeContents(obj);
        selection.removeAllRanges();
        selection.addRange(range);
    } else if ($.browser.safari) {
        var selection = obj.ownerDocument.defaultView.getSelection();
        selection.setBaseAndExtent(obj, 0, obj, 1);
    }
    return this;
}

我在IE8,Firefox,Opera,Safari,Chrome(当前版本)中进行了测试。我不确定它是否适用于较旧的IE版本(真诚的我不在乎)。

答案 3 :(得分:15)

这个thread包含非常棒的东西。但由于“安全错误”,我无法使用FF 3.5b99 + FireBug在此页面上正确执行此操作。

Yipee !!我能够用这段代码选择整个右侧边栏,希望它可以帮助你:

    var r = document.createRange();
    var w=document.getElementById("sidebar");  
    r.selectNodeContents(w);  
    var sel=window.getSelection(); 
    sel.removeAllRanges(); 
    sel.addRange(r); 

PS: - 我无法使用jquery选择器返回的对象,如

   var w=$("div.welovestackoverflow",$("div.sidebar"));

   //this throws **security exception**

   r.selectNodeContents(w);

答案 4 :(得分:7)

我正在寻找同样的事情,我的解决方案是:

$('#el-id').focus().select();

答案 5 :(得分:6)

您可以使用以下功能选择任何元素的内容:

jQuery.fn.selectText = function(){
    this.find('input').each(function() {
        if($(this).prev().length == 0 || !$(this).prev().hasClass('p_copy')) { 
            $('<p class="p_copy" style="position: absolute; z-index: -1;"></p>').insertBefore($(this));
        }
        $(this).prev().html($(this).val());
    });
    var doc = document;
    var element = this[0];
    console.log(this, element);
    if (doc.body.createTextRange) {
        var range = document.body.createTextRange();
        range.moveToElementText(element);
        range.select();
    } else if (window.getSelection) {
        var selection = window.getSelection();        
        var range = document.createRange();
        range.selectNodeContents(element);
        selection.removeAllRanges();
        selection.addRange(range);
    }
};

可以按如下方式调用此函数:

$('#selectme').selectText();

答案 6 :(得分:5)

我喜欢lepe的答案,除了一些事情:

  1. 浏览器嗅探,jQuery或者不是最佳
  2. DRY
  3. 如果obj的父级不支持 createTextRange
  4. ,则无法在IE8中运行
  5. Chrome应该使用 setBaseAndExtent 的能力(IMO)
  6. 不会选择跨越多个DOM元素的文本(“selected”元素中的元素)。换句话说,如果您在包含多个span元素的div上调用 selText ,它将选择每个元素的文本。对我来说这是一个交易破坏者,YMMV。
  7. 这就是我想出来的,并且点了一下lepe的灵感回答。我相信我会被嘲笑,因为这可能有点笨拙(实际上可能更多但我离题了)。但它可以工作并避免浏览器嗅探和这就是

    selectText:function(){
    
        var range,
            selection,
            obj = this[0],
            type = {
                func:'function',
                obj:'object'
            },
            // Convenience
            is = function(type, o){
                return typeof o === type;
            };
    
        if(is(type.obj, obj.ownerDocument)
            && is(type.obj, obj.ownerDocument.defaultView)
            && is(type.func, obj.ownerDocument.defaultView.getSelection)){
    
            selection = obj.ownerDocument.defaultView.getSelection();
    
            if(is(type.func, selection.setBaseAndExtent)){
                // Chrome, Safari - nice and easy
                selection.setBaseAndExtent(obj, 0, obj, $(obj).contents().size());
            }
            else if(is(type.func, obj.ownerDocument.createRange)){
    
                range = obj.ownerDocument.createRange();
    
                if(is(type.func, range.selectNodeContents)
                    && is(type.func, selection.removeAllRanges)
                    && is(type.func, selection.addRange)){
                    // Mozilla
                    range.selectNodeContents(obj);
                    selection.removeAllRanges();
                    selection.addRange(range);
                }
            }
        }
        else if(is(type.obj, document.body) && is(type.obj, document.body.createTextRange)) {
    
            range = document.body.createTextRange();
    
            if(is(type.obj, range.moveToElementText) && is(type.obj, range.select)){
                // IE most likely
                range.moveToElementText(obj);
                range.select();
            }
        }
    
        // Chainable
        return this;
    }
    

    就是这样。您看到的一些内容是为了便于阅读和/或方便。在最新版本的Opera,Safari,Chrome,Firefox和IE上测试了Mac。也在IE8中测试过。此外,我通常只在代码块中需要/当需要时声明变量,但jslint建议将它们全部声明为top。好的jslint。

    修改 我忘了将如何将其与op的代码联系起来:

    function SelectText(element) {
        $("#" + element).selectText();
    }
    

    干杯

答案 7 :(得分:4)

适用于chrome的更新版本:

function SelectText(element) {
    var doc = document;
    var text = doc.getElementById(element);    
    if (doc.body.createTextRange) { // ms
        var range = doc.body.createTextRange();
        range.moveToElementText(text);
        range.select();
    } else if (window.getSelection) {
        var selection = window.getSelection();
        var range = doc.createRange();
        range.selectNodeContents(text);
        selection.removeAllRanges();
        selection.addRange(range);

    }
}

$(function() {
    $('p').click(function() {
        SelectText("selectme");

    });
});

http://jsfiddle.net/KcX6A/326/

答案 8 :(得分:3)

lepe - 这对我很有用,谢谢! 我把你的代码放在一个插件文件中,然后将它与每个语句一起使用,这样你就可以在一个页面上有多个预标签和多个“全选”链接,然后选择正确的预先加亮:

<script type="text/javascript" src="../js/jquery.selecttext.js"></script>
<script type="text/javascript">
  $(document).ready(function() { 
        $(".selectText").each(function(indx) {
                $(this).click(function() {                 
                    $('pre').eq(indx).selText().addClass("selected");
                        return false;               
                    });
        });
  });

答案 9 :(得分:3)

对于任何标记,可以通过这个简短的代码选择该标记内的所有文本。它将使用黄色突出显示整个标记区域,并在单击时选择其中的文本。

document.onclick = function(event) {
    var range, selection;
event.target.style.backgroundColor = 'yellow';
        selection = window.getSelection();
        range = document.createRange();
        range.selectNodeContents(event.target);
        selection.removeAllRanges();
        selection.addRange(range);
};

答案 10 :(得分:2)

看一下Selection object(Gecko引擎)和TextRange object(Trident引擎)。我不知道任何具有跨浏览器支持的JavaScript框架,但是我从来没有找过它,所以甚至jQuery都有可能。

答案 11 :(得分:1)

Tim的方法适用于我的情况 - 在我替换以下语句后,在IE和FF中选择div中的文本:

range.moveToElementText(text);

以下内容:

range.moveToElementText(el);

通过使用以下jQuery函数单击它来选择div中的文本:

$(function () {
    $("#divFoo").click(function () {
        selectElementText(document.getElementById("divFoo"));
    })
});

答案 12 :(得分:1)

这是另一个简单的解决方案,以字符串的形式获取所选文本,您可以轻松地使用此字符串将div元素子句附加到您的代码中:

var text = '';

if (window.getSelection) {
    text = window.getSelection();

} else if (document.getSelection) {
    text = document.getSelection();

} else if (document.selection) {
    text = document.selection.createRange().text;
}

text = text.toString();

答案 13 :(得分:0)

根据select()的jQuery文档:

  

触发每个匹配元素的select事件。这会导致所有已绑定到该select事件的函数被执行,并调用浏览器对匹配元素的默认选择操作。

您有解释为什么jQuery select()在这种情况下不起作用。

答案 14 :(得分:0)

我的特定用例是在可编辑的span元素中选择一个文本范围,据我所知,这里没有描述任何答案。

主要区别在于您必须将Text类型的节点传递给Range对象,如in the documentation of Range.setStart()所述:

  

如果startNode是 Text,Comment或CDATASection 类型的节点,   然后startOffset是从一开始的字符数   的StartNode。对于其他Node类型,startOffset是child的数量   startNode开头之间的节点。

Text节点是span元素的第一个子节点,因此要获取它,请访问span元素的childNodes[0]。其余的与大多数其他答案相同。

这是一个代码示例:

var startIndex = 1;
var endIndex = 5;
var element = document.getElementById("spanId");
var textNode = element.childNodes[0];

var range = document.createRange();
range.setStart(textNode, startIndex);
range.setEnd(textNode, endIndex);

var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);

其他相关文件:
Range
Selection
Document.createRange()
Window.getSelection()

答案 15 :(得分:-1)

为Chrome的“else if”添加了jQuery.browser.webkit。无法在Chrome 23中使用它。

在下方制作此脚本,以选择<pre>标记中包含class="code"的内容。

jQuery( document ).ready(function() {
    jQuery('pre.code').attr('title', 'Click to select all');
    jQuery( '#divFoo' ).click( function() {
        var refNode = jQuery( this )[0];
        if ( jQuery.browser.msie ) {
            var range = document.body.createTextRange();
            range.moveToElementText( refNode );
            range.select();
        } else if ( jQuery.browser.mozilla || jQuery.browser.opera  || jQuery.browser.webkit ) {
            var selection = refNode.ownerDocument.defaultView.getSelection();
            console.log(selection);
            var range = refNode.ownerDocument.createRange();
            range.selectNodeContents( refNode );
            selection.removeAllRanges();
            selection.addRange( range );
        } else if ( jQuery.browser.safari ) {
            var selection = refNode.ownerDocument.defaultView.getSelection();
            selection.setBaseAndExtent( refNode, 0, refNode, 1 );
        }
    } );
} );