Я хочу, чтобы можно было нависнуть над любым словом на веб-странице и получить всплывающее окно над этим словом с этим словом в нем. Кажется, это почти невозможно без огромных проблем с производительностью, поэтому я попытался сделать двойной щелчок, а не зависание.
С помощью двойного щелчка я могу определить текст слова, но я не могу ничего сделать с самим словом на странице. В принципе, я хочу обернуть выделенный текст тегом span, чтобы я мог позиционировать вещи относительно него. Я видел, как это делалось раньше с помощью маркеров, но я не знаю, как это сделать.
Примечание. Это нужно только в Firefox.
Вы можете использовать следующие функции:
var range = window.getSelection().getRangeAt(0);
var newNode = document.createElement("b");
range.surroundContents(newNode);
Это окружает ваш выбор с помощью b-tag.
b
может быть класс?
var range = window.getSelection().getRangeAt(0);range.surroundContents($("<span>", {'class':'test'})[0]);
Это невозможно для события mouseover
. Вы можете использовать document.caretPositionFromPoint()
, который стандартизирован и поддерживается в Firefox 20 и более поздних версиях и возвращается к собственному эквиваленту WebKit.
Шаги при обработке события мыши:
document.caretPositionFromPoint()
или эквивалентgetBoundingClientRect()
в диапазоне, чтобы получить координаты слова Демонстрация довольно ограничена (например, она не работает со словом, пересекающим границы элементов, определение слова очень грубо и существует множество возможностей для оптимизации), но должно быть достаточно, чтобы вы начали. Он работает в текущих браузерах, кроме IE, который не поддерживает document.caretPositionFromPoint()
.
Вот критический код:
function expandToWord(str, offset) {
var start = offset;
while ( start >= 1 && /\S/.test( str.charAt(start - 1) ) ) {
--start;
}
var end = offset, len = str.length;
while ( end < len && /\S/.test( str.charAt(end) ) ) {
++end;
}
return {
start: start,
end: end,
word: str.slice(start, end)
};
}
var wordDiv = document.createElement("div");
wordDiv.className = "word";
var createRangeFromPoint = (function(doc) {
// Try standards-based method first
if (typeof doc.caretPositionFromPoint != "undefined") {
return function(x, y) {
var pos = doc.caretPositionFromPoint(x, y);
var range = null;
if (pos) {
range = doc.createRange();
range.setStart(pos.offsetNode, pos.offset);
range.collapse(true);
}
return range;
};
}
// Now try WebKit proprietary method
else if (typeof doc.caretRangeFromPoint != "undefined") {
return function(x, y) {
return doc.caretRangeFromPoint(x, y);
};
}
// Give up
else {
return function() { return null; };
}
})(document);
function mouseEventHandler(e) {
if (wordDiv.parentNode) {
wordDiv.parentNode.removeChild(wordDiv);
}
var range = createRangeFromPoint(e.clientX, e.clientY);
if (range) {
if (range.startContainer.nodeType == 3) {
var wordInfo = expandToWord(range.startContainer.data, range.startOffset);
if (wordInfo.word) {
range.setStart(range.startContainer, wordInfo.start);
range.setEnd(range.startContainer, wordInfo.end);
var rect = range.getBoundingClientRect();
// Get the difference between client and page coordinates from the event
// for positioning the word div
var offsetX = e.clientX - e.pageX;
var offsetY = e.clientY - e.pageY;
wordDiv.style.left = (rect.left + offsetX) + "px";
wordDiv.style.top = (rect.top + offsetY - 20) + "px";
wordDiv.innerHTML = "";
wordDiv.appendChild( document.createTextNode(wordInfo.word) );
document.body.appendChild(wordDiv);
}
}
}
}
document.onmousemove = mouseEventHandler;
document.onmouseover = mouseEventHandler;
document.onmouseout = mouseEventHandler;
expandToWord()
в примере.