在元素中选择文本(类似于用鼠标高亮显示)

我想让用户点击一个链接,然后它在另一个元素(输入)中选择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();
}

我是不是错过了什么显而易见的东西?

370968 次浏览

看看选择对象 (Gecko引擎)和TextRange对象 (Trident引擎)。我不知道是否有JavaScript框架实现了这种跨浏览器支持,但我也从未寻找过,所以甚至jQuery也可能具有这种支持。

根据jQuery文档select():

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

这就是为什么jQuery select()在这种情况下不能工作的解释。

这个线程 (死链接)包含了非常奇妙的东西。但由于“安全错误”,我无法在此页面上使用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);

纯Javascript

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


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>

这是一个演示工作。对于那些正在寻找jQuery插件的人,我做了这也是其中之一


jQuery(原始答案)

我在这个线程中找到了这个问题的解决方案。我能够修改给出的信息,并将其与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);
}
}

Jason的代码不能用于iframe内的元素(因为作用域不同于window和document)。我修复了这个问题,我修改了它,以便用于任何其他jQuery插件(可链):

例1:选择<代码>标签与单一点击,并添加类“选定”:

$(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版本(我真的不在乎)。

下面是一个没有浏览器嗅探和不依赖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);

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

range.moveToElementText(text);

与以下:

range.moveToElementText(el);

通过下面的jQuery函数点击它来选择div中的文本:

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

麻风-这对我来说很有用,谢谢! 我把你的代码放在一个插件文件中,然后与每个语句一起使用,这样你就可以在一个页面上有多个pre标签和多个“Select all”链接,它会挑出正确的pre来突出显示:

<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;
});
});
});

我也在寻找同样的东西,我的答案是:

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

这是另一个简单的解决方案,以字符串的形式获得选定的文本,你可以使用这个字符串很容易地追加一个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();

更新版本,工作在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/

我喜欢lepe的回答,除了几件事:

  1. 浏览器嗅探,不管有没有jQuery都不是最佳选择
  2. 如果obj的父对象不支持createTextRange,则在IE8中无法工作
  3. Chrome使用setBaseAndExtent的能力应该被利用(IMO)
  4. 不会选择跨越多个DOM元素(“选定”元素中的元素)的文本。换句话说,如果你在包含多个span元素的div上调用selText,它将选择每个元素的文本。这对我来说是一个致命伤,YMMV。

这是我想到的,并向麻风病的答案致敬。我相信我会被嘲笑,因为这可能有点笨拙(实际上可能更严重,但我跑题了)。但它可以工作并避免浏览器嗅探和这就是重点

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;
}

就是这样。你看到的一些是为了可读性和/或便利性。在Mac上测试最新版本的Opera, Safari, Chrome, Firefox和IE。也在IE8中测试过。此外,我通常只声明变量,如果/当需要在代码块内,但jslint建议它们都声明在顶部。jslint。

<强>编辑 我忘记包括如何将其绑定到op的代码:

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

干杯

为Chrome添加jQuery.browser.webkit到“else if”。不能让这个工作在Chrome 23。

下面的脚本用于选择<pre>标记中的内容,该标记具有class="code". c。

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 );
}
} );
} );

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

主要的区别是你必须将一个类型为Text的节点传递给Range对象,如在Range.setStart()的文档中所述:

如果startNode是一个类型为文本,注释或CDATASection的节点, 那么startOffset是从开始的字符数 startNode。对于其他Node类型,startOffset是子节点的编号

.

.

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);

其他相关文档:
. zip 范围 < br > 选择 < br > Document.createRange () < br > Window.getSelection () < / p >

你可以使用下面的函数来选择任何元素的内容:

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();

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

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);
};