Единственный способ, который я могу придумать, заключается в том, чтобы обернуть каждое слово в элементе span, а затем использовать document.elementFromPoint (x, y) , чтобы получить элемент span в заданном место нахождения. Как то так:
function highlightWordAtXY(x, y) {
// Get the element containing the text
var par = document.elementFromPoint(x, y),
// textContent or innerText ?
t = "textContent" in par ? "textContent" : "innerText",
// Get the text of the element. No pun intended on the par[t].
text = par[t],
result;
// Wrap a span around every word
par.innerHTML = text.replace(/\b(\w+)\b/g, "<span>$1</span>");
// Get the elementFromPoint again, should be a span this time
result = document.elementFromPoint(x, y);
// Check that we actually clicked on a word
if (result == par)
return false;
// Wrap HTML text around the text at x, y
result[t] = '<span class="highlight">' + result[t] + '</span>';
// Restore the content with the wrapped text
par.innerHTML = par[t];
}
Пример на http://jsfiddle.net/BSHYp/1/show/light/ - щелкните слово и посмотрите, как оно выделено.
Некоторые важные замечания здесь:
- Каждый блок текста должен быть заключен в элемент (например,
<p>
или <div>
). В любом случае вы должны заключать абзацы в теги <p>
,
- Элемент в данном месте (x, y) должен содержать только текст, без дочерних элементов HTML . У текстовых узлов с родственными HTML-элементами они будут удалены (например, при нажатии «Некоторые» или «здесь» в
Some <b>text</b> here
будут удалены теги <b>
). Разделение их на отдельные элементы <span>
было бы единственным решением без построения гораздо более сложной процедуры
- IE выдаст «Неизвестную ошибку времени выполнения», если вы попытаетесь добавить элемент уровня блока в тег
<p>
,
- На очень, очень, очень больших блоках текста вы можете столкнуться с проблемами производительности. Разбейте их, где это применимо.