Как выделить текст объекта DOM Range?
Я выделяю некоторый текст на html-странице (открытой в Firefox) с помощью мыши и, используя функции JavaScript, создаю / получаю объект range, соответствующий выделенному тексту.
userSelection =window.getSelection();
var rangeObject = getRangeObject(userSelection);
Теперь я хочу выделить весь текст, который попадает под диапазон объекта. Я делаю это так,
var span = document.createElement("span");
rangeObject.surroundContents(span);
span.style.backgroundColor = "yellow";
Ну, это работает нормально, только когда rangeobject (начальная точка и конечная точка) находится в одном и том же текстовом узле, тогда он выделяет соответствующий текст.
<p>In this case,the text selected will be highlighted properly,
because the selected text lies under a single textnode</p>
Но если диапазон объекта охватывает более одного текстового узла, то он не работает должным образом, он выделяет только те тексты, которые находятся в первом текстовом узле, например
<p><h3>In this case</h3>, only the text inside the header(h3)
will be highlighted, not any text outside the header</p>
Любая идея, как я могу сделать, все тексты, которые подпадают под rangeobject, выделены, независимо от того, лежит ли диапазон в одном узле или нескольких узлах? Спасибо....
4 ответа
Я бы предложил использовать document
или TextRange
"s execCommand
метод, который построен именно для этой цели, но обычно используется в редактируемых документах. Вот ответ, который я дал на аналогичный вопрос:
Следующее должно делать то, что вы хотите. В браузерах, отличных от IE, он включает designMode, применяет цвет фона, а затем снова выключает designMode.
ОБНОВИТЬ
Исправлена работа в IE 9.
ОБНОВЛЕНИЕ 12 сентября 2013
Вот ссылка, подробно описывающая метод удаления бликов, созданных этим методом:
function makeEditableAndHighlight(colour) {
var range, sel = window.getSelection();
if (sel.rangeCount && sel.getRangeAt) {
range = sel.getRangeAt(0);
}
document.designMode = "on";
if (range) {
sel.removeAllRanges();
sel.addRange(range);
}
// Use HiliteColor since some browsers apply BackColor to the whole block
if (!document.execCommand("HiliteColor", false, colour)) {
document.execCommand("BackColor", false, colour);
}
document.designMode = "off";
}
function highlight(colour) {
var range;
if (window.getSelection) {
// IE9 and non-IE
try {
if (!document.execCommand("BackColor", false, colour)) {
makeEditableAndHighlight(colour);
}
} catch (ex) {
makeEditableAndHighlight(colour)
}
} else if (document.selection && document.selection.createRange) {
// IE <= 8 case
range = document.selection.createRange();
range.execCommand("BackColor", false, colour);
}
}
Rangy - это кросс-браузерная библиотека выбора и выбора, которая отлично решает эту проблему с помощью модуля CSS Class Applier. Я использую его для реализации подсветки в различных браузерах и на iPad, и он работает отлично.
Ответ Тима Дауна великолепен, но Рэнги избавляет вас от необходимости самостоятельно писать и поддерживать все эти коды обнаружения функций.
var userSelection = document.getSelection();
var range = userSelection.getRangeAt(0);
Вместо метода SurroundContent вы можете использовать методы appendChild и extractContents следующим образом:
let newNode = document.createElement('mark');
newNode.appendChild(range.extractContents());
range.insertNode(newNode);
function markNode() {
if(document.getSelection() && document.getSelection().toString().length){
let range = document.getSelection().getRangeAt(0);
let newNode = document.createElement('mark');
newNode.appendChild(range.extractContents());
range.insertNode(newNode);
}
else{
alert('please make selection of text to mark');
}
}
function resetContent() {
testMe.innerHTML = `Remember: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Node">Read</a> and <strong>stay strong</strong>`;
}
<p id="testMe">Remember: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Node">Read</a> and <strong>stay strong</strong></p>
<div><button onclick="markNode()">markNode</button></div>
<div><button onclick="resetContent()">resetContent</button></div>
Не могли бы вы уточнить необходимость этой функциональности. Если вы хотите изменить только стиль выделения выделенного текста, вы можете использовать CSS: '::selection'
Дополнительная информация: http://www.quirksmode.org/css/selection.html https://developer.mozilla.org/en/CSS/::selection
Можете ли вы попробовать добавить класс для окружающего диапазона и применить иерархический CSS?
var span = document.createElement("span");
span.className="selection";
rangeObject.surroundContents(span);
В определении CSS
span.selection, span.selection * {
background-color : yellow;
}
Я не пробовал это. Но только догадываюсь, что это сработает.