У меня есть script, который изменяет цвет фона текста, который был выбран. Однако я сталкиваюсь с проблемой, когда текст выбран из нескольких элементов/тегов.
Код, который у меня есть:
var text = window.getSelection().getRangeAt(0);
var colour = document.createElement("hlight");
colour.style.backgroundColor = "Yellow";
text.surroundContents(colour);
И выводимая ошибка:
Error: The boundary-points of a range does not meet specific requirements. =
NS_ERROR_DOM_RANGE_BAD_BOUNDARYPOINTS_ERR
Line: 7
Я считаю, что это связано с функцией getRange(), хотя я не слишком уверен, как действовать, поскольку я начинаю на javascript.
Есть ли другой способ воспроизвести то, что я пытаюсь достичь?
Большое спасибо.
Ответ 1
Этот вопрос задан сегодня: Как я могу выделить текст объекта DOM Range?
Вот мой ответ:
Следующее должно делать то, что вы хотите. В браузерах, отличных от IE, он включает designMode, применяет цвет фона и затем снова отключает designMode.
UPDATE
Исправлено для работы в IE 9.
function makeEditableAndHighlight(colour) {
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, sel;
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);
}
}
Ответ 2
Я думаю, что использование mark.js в этом случае велико. Предпочтение библиотеки состоит в том, чтобы выделить все экземпляры определенного слова в документе HTML, но его можно настроить с помощью функции параметра фильтр, а дополнительные атрибуты span можно добавить через каждый функция опций.
function markFunc(node, text, color) {
var instance = new Mark(node);
instance.mark(text, {
"element": "span",
"className": color,
"acrossElements": true,
"separateWordSearch": false,
"accuracy": "partially",
"diacritics": true,
"ignoreJoiners": true,
"each": function(element) {
element.setAttribute("id", "sohayb");
element.setAttribute("title", "sohayb_title");
},
"done":function(totalMarks) {
window.getSelection().empty();//This only in Chrome
console.log("total marks: " + totalMarks);
},
"filter": function(node, term, totalCounter, counter) {
var res = false;
if (counter == 0) {
res = selectionRange.isPointInRange(node, selectionRange.startOffset);
} else {
res = selectionRange.isPointInRange(node, 1);
}
console.log("Counter: " + counter + ", startOffset: " + selectionRange.startOffset);
return res;
}
});
};
Отметьте образец JSFiddle для завершенного кода, который выделяет выбор пользователя, даже для нескольких элементов HTML.