Выбор текста в элементе (сродни подсветке мышью)
Я хотел бы, чтобы пользователи щелкали по ссылке, затем выбирает текст HTML в другом элементе (а не вводе).
Под "select" я подразумеваю то же самое, что вы бы выделили текст, перетащив на него указатель мыши. Это было медведем для исследования, потому что все говорят о "выборе" или "подчеркивании" в других терминах.
Возможно ли это? Мой код:
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();
}
Я пропустил что-то явно очевидное?
Ответы
Ответ 1
Я нашел решение для этого, благодаря этой теме, найденной TheVillageIdiot. Мне удалось изменить предоставленную информацию и смешать ее с немного 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);
}
}
EDIT (9/28/11):
Прошло некоторое время, так как этот ответ был обновлен, и я многому научился, как разработчик, так как я спросил и ответил на этот вопрос. Он также получил гораздо больше внимания, чем я думал. Я хочу предоставить лучшее решение, чем оригинальное, которое я разместил, которое не полагается на устаревшие методы jQuery или вообще jQuery. Не могли бы вы использовать jQuery, чтобы помочь вам? Конечно, но если вы можете добиться того же результата без jQuery и использовать обнаружение функции вместо того, чтобы обнюхивать браузер, почему бы вам не так? Итак, ниже мой обновленный ответ:
function SelectText(element) {
var doc = document
, text = doc.getElementById(element)
, range, selection
;
if (doc.body.createTextRange) {
range = document.body.createTextRange();
range.moveToElementText(text);
range.select();
} else if (window.getSelection) {
selection = window.getSelection();
range = document.createRange();
range.selectNodeContents(text);
selection.removeAllRanges();
selection.addRange(range);
}
}
document.onclick = function(e) {
if (e.target.className === 'click') {
SelectText('selectme');
}
};
<div id="selectme"><p>Some text goes here!</p><p>Moar text!</p></div>
<p class="click">Click me!</p>
Ответ 2
Здесь версия без браузера, нюхающая и не полагающаяся на 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);
Ответ 3
Код Jason не может использоваться для элементов внутри iframe (поскольку область отличается от окна и документа). Я исправил эту проблему, и я ее модифицировал, чтобы использовать ее как любой другой плагин jQuery (chainable):
Пример 1: Выбор всего текста внутри <code> с одним щелчком мыши и добавить класс "selected":
$(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 (искренне мне все равно).
Ответ 4
Этот поток содержит действительно замечательные вещи. Но я не могу сделать это прямо на этой странице, используя 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);
Ответ 5
Я искал одно и то же, мое решение было следующим:
$('#el-id').focus().select();
Ответ 6
Мне понравился ответ lepe, за исключением нескольких вещей:
- Браузер-нюхание, jQuery или нет не оптимально
- DRY
- Не работает в IE8, если родительский элемент obj не поддерживает createTextRange
- Возможность Chrome использовать setBaseAndExtent должна быть использована (IMO)
- Не будет выбирать текст, охватывающий несколько элементов DOM (элементы в элементе "selected" ). Другими словами, если вы вызываете selText в div, содержащий несколько элементов span, он не будет выбирать текст каждого из этих элементов. Для меня это был развязкой, YMMV.
Вот то, что я придумал, с кивком, чтобы ответить за вдох. Я уверен, что меня будут высмеивать, поскольку это, возможно, немного тяжело (и на самом деле может быть moreso, но я отвлекаюсь). Но он работает и избегает обнюхивания браузеров и что точка.
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 предположил, что все они объявлены вверху. Ok jslint.
Edit
Я забыл включить, как связать это с op-кодом:
function SelectText(element) {
$("#" + element).selectText();
}
Приветствия
Ответ 7
Обновленная версия, которая работает в 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
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
Вы можете использовать следующую функцию для выбора содержимого любого элемента:
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();
Ответ 10
Посмотрите объект выделения (движок Gecko) и Объект TextRange (Trident engine.) Я не знаю ни одного фреймворка JavaScript, который поддерживает кросс-браузер для этого, но я никогда не искал его, поэтому возможно, что даже у него есть jQuery.
Ответ 11
Метод Tim отлично работает для моего случая - выбирая текст в div для IE и FF после того, как я заменил следующий оператор:
range.moveToElementText(text);
со следующим:
range.moveToElementText(el);
Текст в div выбирается щелчком по нему со следующей функцией jQuery:
$(function () {
$("#divFoo").click(function () {
selectElementText(document.getElementById("divFoo"));
})
});
Ответ 12
вот еще одно простое решение для получения выделенного текста в виде строки, вы можете легко использовать эту строку для добавления дочернего элемента 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
Для любого тега можно выделить весь текст внутри этого тега этим коротким и простым кодом. Он выделит всю область тегов желтым цветом и выделит текст внутри него одним щелчком мыши.
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);
};
Ответ 14
Согласно документации jQuery select()
:
Запустить событие выбора каждого совпадающего элемента. Это приводит к тому, что все функции, связанные с этим событием select, будут выполнены, и вызывает действие выбора по умолчанию для браузера по соответствующим элементам.
Есть ваше объяснение, почему jQuery select()
не будет работать в этом случае.
Ответ 15
Добавлен jQuery.browser.webkit
в "else if" для Chrome. Не удалось заставить это работать в Chrome 23.
Сделал это script ниже для выбора содержимого в теге <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 );
}
} );
} );
Ответ 16
В моем конкретном примере использования был выбран диапазон текста внутри редактируемого элемента span, который, насколько я мог видеть, не описан ни в одном из ответов здесь.
Основное отличие состоит в том, что вам нужно передать node типа Text
в объект Range
, как описано в документации Range.setStart():
Если startNode является node типа Текст, Комментарий или CDATASection, то startOffset - это количество символов с начала startNode. Для других типов node startOffset - это число дочерних узлов между началом startNode.
Text
node - это первый дочерний элемент node элемента span, поэтому для его получения обращайтесь к childNodes[0]
элемента span. Остальное такое же, как и в большинстве других ответов.
Вот пример кода:
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()