如何使用 JavaScript 获取光标下的单词?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2444430/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get a word under cursor using JavaScript?
提问by Ivan
If I for example have
例如,如果我有
<p> some long text </p>
on my HTML page, how can I know that cursor of mouse is for example above the word 'text'?
在我的 HTML 页面上,我怎么知道鼠标光标位于单词“文本”上方?
采纳答案by Damovisa
Further to the two other answers, you may be able to split your paragraphs up into spans using jQuery (or javascript generally).
除了其他两个答案之外,您可以使用 jQuery(或通常使用 javascript)将您的段落拆分为跨度。
That way, you wouldn't need to think about outputting your text with spans around the words. Let your javascript do it for you.
这样,您就无需考虑在单词周围输出带有跨度的文本。让您的 javascript 为您完成。
e.g.
例如
<p>Each word will be wrapped in a span.</p>
<p>A second paragraph here.</p>
Word: <span id="word"></span>
<script type="text/javascript">
$(function() {
// wrap words in spans
$('p').each(function() {
var $this = $(this);
$this.html($this.text().replace(/\b(\w+)\b/g, "<span></span>"));
});
// bind to each span
$('p span').hover(
function() { $('#word').text($(this).css('background-color','#ffff66').text()); },
function() { $('#word').text(''); $(this).css('background-color',''); }
);
});
</script>
Note that the above code, while it works, will strip out any html inside your paragraph tags.
请注意,上面的代码虽然有效,但会删除段落标签内的任何 html。
回答by Eyal
My other answer works only in Firefox. This answer works in Chrome. (Might work in Firefox, too, I don't know.)
我的另一个答案仅适用于 Firefox。此答案适用于 Chrome。(也可能在 Firefox 中工作,我不知道。)
function getWordAtPoint(elem, x, y) {
if(elem.nodeType == elem.TEXT_NODE) {
var range = elem.ownerDocument.createRange();
range.selectNodeContents(elem);
var currentPos = 0;
var endPos = range.endOffset;
while(currentPos+1 < endPos) {
range.setStart(elem, currentPos);
range.setEnd(elem, currentPos+1);
if(range.getBoundingClientRect().left <= x && range.getBoundingClientRect().right >= x &&
range.getBoundingClientRect().top <= y && range.getBoundingClientRect().bottom >= y) {
range.expand("word");
var ret = range.toString();
range.detach();
return(ret);
}
currentPos += 1;
}
} else {
for(var i = 0; i < elem.childNodes.length; i++) {
var range = elem.childNodes[i].ownerDocument.createRange();
range.selectNodeContents(elem.childNodes[i]);
if(range.getBoundingClientRect().left <= x && range.getBoundingClientRect().right >= x &&
range.getBoundingClientRect().top <= y && range.getBoundingClientRect().bottom >= y) {
range.detach();
return(getWordAtPoint(elem.childNodes[i], x, y));
} else {
range.detach();
}
}
}
return(null);
}
In your mousemove handler, call getWordAtPoint(e.target, e.x, e.y);
在您的 mousemove 处理程序中,调用 getWordAtPoint(e.target, e.x, e.y);
回答by Drakes
Preamble:
前言:
If you have multiple spans and nested HTML that separate words (or even characters in words), then all the above solutions will have trouble returning the full and correct word.
如果您有多个跨度和嵌套的 HTML 来分隔单词(甚至单词中的字符),那么上述所有解决方案都将无法返回完整且正确的单词。
Here is an example from the bounty question: Х</span>rт0съ. How to properly return Хrт0съ? These issues were not addressed back in 2010, so I will present two solutions now (2015).
下面是从赏金问题的例子:Х</span>rт0съ。如何正确退货Хrт0съ?这些问题在 2010 年没有得到解决,所以我现在将提出两个解决方案(2015 年)。
Solution 1 - Strip inner tags, wrap spans around each full word:
解决方案 1 - 去除内部标签,环绕每个完整单词:
One solution is to strip out the span tags inside paragraphs but preserve their text. Split words and phrases are thus joined back together as regular text. Each word is found by whitespace division (not just a space), and those words are wrapped in spans which can be individually accessed.
一种解决方案是去除段落内的跨度标签,但保留其文本。拆分的单词和短语因此重新连接在一起作为常规文本。每个单词都是通过空格分割(不仅仅是空格)找到的,这些单词被包装在可以单独访问的跨度中。
In the demo, you can highlight the entire word and thus get the text of the whole word.
在演示中,您可以突出显示整个单词,从而获取整个单词的文本。


Code:
代码:
$(function() {
// Get the HTML in #hoverText - just a wrapper for convenience
var $hoverText = $("#hoverText");
// Replace all spans inside paragraphs with their text
$("p span", $hoverText).each(function() {
var $this = $(this);
var text = $this.text(); // get span content
$this.replaceWith(text); // replace all span with just content
});
// Wrap words in spans AND preserve the whitespace
$("p", $hoverText).each(function() {
var $this = $(this);
var newText = $this.text().replace(/([\s])([^\s]+)/g, "<span></span>");
newText = newText.replace(/^([^\s]+)/g, "<span></span>");
$this.empty().append(newText);
});
// Demo - bind hover to each span
$('#hoverText span').hover(
function() { $(this).css('background-color', '#ffff66'); },
function() { $(this).css('background-color', ''); }
);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="hoverText">
<p><span class="kinovar"><span id="selection_index3337" class="selection_index"></span>По f7-мъ часЁ твори1тъ сщ7eнникъ начaло съ кади1ломъ и3 со свэщeю, цrкимъ двeремъ tвeрз?ннымъ, и3 поeтъ: Х</span>rт0съ воскRсе: <span class="kinovar">со
ст?хи2. И# по ст?сёхъ pал0мъ: Б</span>лгcви2 душE моS гDа: <span class="kinovar">И# ?3ктен?A. Тaже каfjсма nбhчнаz.</span>
</p>
</div>
Solution 1 full-text demo
方案一全文演示
Solution 2 - Caret inspection and DOM traversal:
解决方案 2 - Caret 检查和 DOM 遍历:
Here is a more sophisticated solution. It's an algorithmic solution using node traversal that accurately captures the full and correct word under a cursor in a text node.
这是一个更复杂的解决方案。它是一种使用节点遍历的算法解决方案,可准确捕获文本节点中光标下的完整和正确单词。
A temporary word is found by checking the caret position (using caretPositionFromPointor caretRangeFromPoint, credits for the idea to @chrisv). This may or may not be the full word, yet.
通过检查插入符号位置(使用caretPositionFromPoint或caretRangeFromPoint,将想法归功于@chrisv)找到一个临时词。这可能是也可能不是完整的词。
It is then analyzed to see if it is at either edge of its text node (beginning or end). If it is, the previous text node or the following text node is examined to see if it should be joined to make this word fragment longer.
然后对其进行分析以查看它是否位于其文本节点的任一边缘(开始或结束)。如果是,则检查前一个文本节点或后一个文本节点以查看是否应将其连接起来以使该单词片段更长。
Example:
例子:
Х</span>rт0съmust return Хrт0съ, not Хnor rт0съ.
Х</span>rт0съ必须返回Хrт0съ,而Х不是rт0съ。
The DOM tree is traversed to get the next non-barrier text node. If two word fragments are separated by a <p>or some other barrier tag, then they are not adjacent and thus not part of the same word.
遍历 DOM 树以获取下一个无障碍文本节点。如果两个单词片段被一个<p>或某个其他屏障标记分隔,则它们不相邻,因此不是同一个单词的一部分。
Example:
例子:
?б.)</p><p>Воshould not return ?б.)Во
?б.)</p><p>Во不应该回来 ?б.)Во
In the demo, the left floating div is the word under the cursor. The right floating div, if visible, shows how a word on a boundary was formed. Other tags can safely be inline'd with the text in this solution.
在demo中,左边浮动的div就是光标下的单词。右侧浮动 div(如果可见)显示边界上的单词是如何形成的。其他标签可以安全地与此解决方案中的文本内联。


Code:
代码:
$(function() {
// Get the HTML in #hoverText - just a wrapper for convenience
var $hoverText = $("#hoverText");
// Get the full word the cursor is over regardless of span breaks
function getFullWord(event) {
var i, begin, end, range, textNode, offset;
// Internet Explorer
if (document.body.createTextRange) {
try {
range = document.body.createTextRange();
range.moveToPoint(event.clientX, event.clientY);
range.select();
range = getTextRangeBoundaryPosition(range, true);
textNode = range.node;
offset = range.offset;
} catch(e) {
return ""; // Sigh, IE
}
}
// Firefox, Safari
// REF: https://developer.mozilla.org/en-US/docs/Web/API/Document/caretPositionFromPoint
else if (document.caretPositionFromPoint) {
range = document.caretPositionFromPoint(event.clientX, event.clientY);
textNode = range.offsetNode;
offset = range.offset;
// Chrome
// REF: https://developer.mozilla.org/en-US/docs/Web/API/document/caretRangeFromPoint
} else if (document.caretRangeFromPoint) {
range = document.caretRangeFromPoint(event.clientX, event.clientY);
textNode = range.startContainer;
offset = range.startOffset;
}
// Only act on text nodes
if (!textNode || textNode.nodeType !== Node.TEXT_NODE) {
return "";
}
var data = textNode.textContent;
// Sometimes the offset can be at the 'length' of the data.
// It might be a bug with this 'experimental' feature
// Compensate for this below
if (offset >= data.length) {
offset = data.length - 1;
}
// Ignore the cursor on spaces - these aren't words
if (isW(data[offset])) {
return "";
}
// Scan behind the current character until whitespace is found, or beginning
i = begin = end = offset;
while (i > 0 && !isW(data[i - 1])) {
i--;
}
begin = i;
// Scan ahead of the current character until whitespace is found, or end
i = offset;
while (i < data.length - 1 && !isW(data[i + 1])) {
i++;
}
end = i;
// This is our temporary word
var word = data.substring(begin, end + 1);
// Demo only
showBridge(null, null, null);
// If at a node boundary, cross over and see what
// the next word is and check if this should be added to our temp word
if (end === data.length - 1 || begin === 0) {
var nextNode = getNextNode(textNode);
var prevNode = getPrevNode(textNode);
// Get the next node text
if (end == data.length - 1 && nextNode) {
var nextText = nextNode.textContent;
// Demo only
showBridge(word, nextText, null);
// Add the letters from the next text block until a whitespace, or end
i = 0;
while (i < nextText.length && !isW(nextText[i])) {
word += nextText[i++];
}
} else if (begin === 0 && prevNode) {
// Get the previous node text
var prevText = prevNode.textContent;
// Demo only
showBridge(word, null, prevText);
// Add the letters from the next text block until a whitespace, or end
i = prevText.length - 1;
while (i >= 0 && !isW(prevText[i])) {
word = prevText[i--] + word;
}
}
}
return word;
}
// Return the word the cursor is over
$hoverText.mousemove(function(e) {
var word = getFullWord(e);
if (word !== "") {
$("#result").text(word);
}
});
});
// Helper functions
// Whitespace checker
function isW(s) {
return /[ \f\n\r\t\v\u00A0\u2028\u2029]/.test(s);
}
// Barrier nodes are BR, DIV, P, PRE, TD, TR, ...
function isBarrierNode(node) {
return node ? /^(BR|DIV|P|PRE|TD|TR|TABLE)$/i.test(node.nodeName) : true;
}
// Try to find the next adjacent node
function getNextNode(node) {
var n = null;
// Does this node have a sibling?
if (node.nextSibling) {
n = node.nextSibling;
// Doe this node's container have a sibling?
} else if (node.parentNode && node.parentNode.nextSibling) {
n = node.parentNode.nextSibling;
}
return isBarrierNode(n) ? null : n;
}
// Try to find the prev adjacent node
function getPrevNode(node) {
var n = null;
// Does this node have a sibling?
if (node.previousSibling) {
n = node.previousSibling;
// Doe this node's container have a sibling?
} else if (node.parentNode && node.parentNode.previousSibling) {
n = node.parentNode.previousSibling;
}
return isBarrierNode(n) ? null : n;
}
// REF: http://stackoverflow.com/questions/3127369/how-to-get-selected-textnode-in-contenteditable-div-in-ie
function getChildIndex(node) {
var i = 0;
while( (node = node.previousSibling) ) {
i++;
}
return i;
}
// All this code just to make this work with IE, OTL
// REF: http://stackoverflow.com/questions/3127369/how-to-get-selected-textnode-in-contenteditable-div-in-ie
function getTextRangeBoundaryPosition(textRange, isStart) {
var workingRange = textRange.duplicate();
workingRange.collapse(isStart);
var containerElement = workingRange.parentElement();
var workingNode = document.createElement("span");
var comparison, workingComparisonType = isStart ?
"StartToStart" : "StartToEnd";
var boundaryPosition, boundaryNode;
// Move the working range through the container's children, starting at
// the end and working backwards, until the working range reaches or goes
// past the boundary we're interested in
do {
containerElement.insertBefore(workingNode, workingNode.previousSibling);
workingRange.moveToElementText(workingNode);
} while ( (comparison = workingRange.compareEndPoints(
workingComparisonType, textRange)) > 0 && workingNode.previousSibling);
// We've now reached or gone past the boundary of the text range we're
// interested in so have identified the node we want
boundaryNode = workingNode.nextSibling;
if (comparison == -1 && boundaryNode) {
// This must be a data node (text, comment, cdata) since we've overshot.
// The working range is collapsed at the start of the node containing
// the text range's boundary, so we move the end of the working range
// to the boundary point and measure the length of its text to get
// the boundary's offset within the node
workingRange.setEndPoint(isStart ? "EndToStart" : "EndToEnd", textRange);
boundaryPosition = {
node: boundaryNode,
offset: workingRange.text.length
};
} else {
// We've hit the boundary exactly, so this must be an element
boundaryPosition = {
node: containerElement,
offset: getChildIndex(workingNode)
};
}
// Clean up
workingNode.parentNode.removeChild(workingNode);
return boundaryPosition;
}
// DEMO-ONLY code - this shows how the word is recombined across boundaries
function showBridge(word, nextText, prevText) {
if (nextText) {
$("#bridge").html("<span class=\"word\">" + word + "</span> | " + nextText.substring(0, 20) + "...").show();
} else if (prevText) {
$("#bridge").html("..." + prevText.substring(prevText.length - 20, prevText.length) + " | <span class=\"word\">" + word + "</span>").show();
} else {
$("#bridge").hide();
}
}
.kinovar { color:red; font-size:20px;}.slavic { color: blue;}#result {top:10px;left:10px;}#bridge { top:10px; right:80px;}.floater { position: fixed; background-color:white; border:2px solid black; padding:4px;}.word { color:blue;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <div id="bridge" class="floater"></div> <div id="result" class="floater"></div> <div id="hoverText"><p><span class="kinovar"><span id="selection_index3337" class="selection_index"></span>По f7-мъ часЁ твори1тъ сщ7eнникъ начaло съ кади1ломъ и3 со свэщeю, цrкимъ двeремъ tвeрз?ннымъ, и3 поeтъ: Х</span>rт0съ воскRсе: <span class="kinovar">со ст?хи2. И# по ст?сёхъ pал0мъ: Б</span>лгcви2 душE моS гDа: <span class="kinovar">И# ?3ктен?A. Тaже каfjсма nбhчнаz.</span></p><div class="slavic"> <input value="Works around other tags!"><p><span id="selection_index3737" class="selection_index"></span>(л. рo7з ?б.)</p><p><span class="kinovar"><span id="selection_index3738" class="selection_index"></span>Во вт0рникъ вeчера</span> </p><p><span class="kinovar"><span id="selection_index3739" class="selection_index"></span>tдaн?е прaздника пaсхи.</span></p><p><span class="kinovar"><span id="selection_index3740" class="selection_index"></span>По f7-мъ часЁ твори1тъ сщ7eнникъ начaло съ кади1ломъ и3 со свэщeю, цrкимъ двeремъ tвeрз?ннымъ, и3 поeтъ: Х</span>rт0съ воскRсе: <span class="kinovar">со ст?хи2. И# по ст?сёхъ pал0мъ: Б</span>лгcви2 душE моS гDа: <span class="kinovar">И# ?3ктен?A. Тaже каfjсма nбhчнаz.<input value="Works around inline tags too"></span></p><p><span class="kinovar"><span id="selection_index3741" class="selection_index"></span>На ГDи воззвaхъ: поeмъ ст?хи6ры самоглaсны, слэпaгw, на ?7. Глaсъ в7:</span></p></div>
(Note:I took the liberty of applying styles to the span tags that were present in your sample HTML to illuminate where text node borders are.)
(注意:我冒昧地将样式应用于示例 HTML 中的 span 标签,以阐明文本节点边框的位置。)
Solution 2 full-text demo
方案二全文演示
(Working in Chrome and IE so far. For IE, a method from IERangehad to be used as a shim for cross-browser compatibility)
(目前在 Chrome 和 IE 中工作。对于 IE,必须使用来自IERange的方法作为跨浏览器兼容性的垫片)
回答by Matt
To my knowledge, you can't.
据我所知,你不能。
Only thing I can think of is to put each of the words in their own element, then apply mouse over events to those elements.
我唯一能想到的是将每个单词放在它们自己的元素中,然后将鼠标悬停事件应用于这些元素。
<p><span>Some</span> <span>long</span> <span>text</span></p>
<script>
$(document).ready(function () {
$('p span').bind('mouseenter', function () {
alert($(this).html() + " is what you're currently hovering over!");
});
});
</script>
回答by erwaman
Here's a simple solution that works in Chrome for most cases:
这是一个在 Chrome 中适用于大多数情况的简单解决方案:
function getWordAtPoint(x, y) {
var range = document.caretRangeFromPoint(x, y);
if (range.startContainer.nodeType === Node.TEXT_NODE) {
range.expand('word');
return range.toString().trim();
}
return null;
}
I leave filtering out punctuation and properly handling hyphenated words as an exercise to the reader :).
我将过滤标点符号和正确处理带连字符的单词作为练习留给读者:)。
回答by chrisv
There is an API for this in the current CSSOM View draft: document.caretPositionFromPoint(x,y)
在当前的CSSOM 视图草案中有一个用于此的 API :document.caretPositionFromPoint(x,y)
You would have to check which browser supports this, though. Firefox 7 seems not to support it at all, whereas bug reports indicate Firefox 9 will. Chrome 14 supports caretRangeFromPoint(x,y)which is essentially the same, but from an older CSSOM draft.
不过,您必须检查哪个浏览器支持此功能。Firefox 7 似乎根本不支持它,而错误报告表明 Firefox 9 会支持。Chrome 14 支持caretRangeFromPoint(x,y)基本相同,但来自较旧的 CSSOM 草案。
回答by Ludovic Feltz
Here is the solution for the bounty.
这是赏金的解决方案。
As suggested by chrisvyou can use document.caretRangeFromPoint(chrome) or document.caretPositionFromPoint(Firefox).
I think this solution better answer your question as it doesn't alter your text or the DOM.
根据chrisv 的建议,您可以使用document.caretRangeFromPoint(chrome) 或document.caretPositionFromPoint(Firefox)。我认为此解决方案可以更好地回答您的问题,因为它不会改变您的文本或 DOM。
This function return the word under the mouse cursor without altering the DOM:
这个函数在不改变 DOM 的情况下返回鼠标光标下的单词:
From the document.caretRangeFromPointdocumentation:
从document.caretRangeFromPoint文档:
The caretRangeFromPoint() method of the Document interface returns a Range object for the document fragment under the specified coordinates.
Document 接口的 caretRangeFromPoint() 方法为指定坐标下的文档片段返回一个 Range 对象。
From the document.caretPositionFromPointdocumentation:
从document.caretPositionFromPoint文档:
This method is used to retrieve the caret position in a document based on two coordinates. A CaretPosition is returned, containing the found DOM node and the character offset in that node.
此方法用于根据两个坐标检索文档中的插入符号位置。返回一个 CaretPosition,包含找到的 DOM 节点和该节点中的字符偏移量。
The two function are slightly different but they both return the node containing the text and the offset of the cursor in this text. So it is easy to get the word under the mouse.
这两个函数略有不同,但它们都返回包含文本的节点以及该文本中光标的偏移量。所以很容易得到鼠标下的单词。
See the full example:
查看完整示例:
$(function () {
function getWordUnderCursor(event) {
var range, textNode, offset;
if (document.body.createTextRange) { // Internet Explorer
try {
range = document.body.createTextRange();
range.moveToPoint(event.clientX, event.clientY);
range.select();
range = getTextRangeBoundaryPosition(range, true);
textNode = range.node;
offset = range.offset;
} catch(e) {
return "";
}
}
else if (document.caretPositionFromPoint) { // Firefox
range = document.caretPositionFromPoint(event.clientX, event.clientY);
textNode = range.offsetNode;
offset = range.offset;
} else if (document.caretRangeFromPoint) { // Chrome
range = document.caretRangeFromPoint(event.clientX, event.clientY);
textNode = range.startContainer;
offset = range.startOffset;
}
//data contains a full sentence
//offset represent the cursor position in this sentence
var data = textNode.data,
i = offset,
begin,
end;
//Find the begin of the word (space)
while (i > 0 && data[i] !== " ") { --i; };
begin = i;
//Find the end of the word
i = offset;
while (i < data.length && data[i] !== " ") { ++i; };
end = i;
//Return the word under the mouse cursor
return data.substring(begin, end);
}
//Get the HTML in a div #hoverText and detect mouse move on it
var $hoverText = $("#hoverText");
$hoverText.mousemove(function (e) {
var word = getWordUnderCursor(e);
//Show the word in a div so we can test the result
if (word !== "")
$("#testResult").text(word);
});
});
// This code make it works with IE
// REF: https://stackoverflow.com/questions/3127369/how-to-get-selected-textnode-in-contenteditable-div-in-ie
function getTextRangeBoundaryPosition(textRange, isStart) {
var workingRange = textRange.duplicate();
workingRange.collapse(isStart);
var containerElement = workingRange.parentElement();
var workingNode = document.createElement("span");
var comparison, workingComparisonType = isStart ?
"StartToStart" : "StartToEnd";
var boundaryPosition, boundaryNode;
// Move the working range through the container's children, starting at
// the end and working backwards, until the working range reaches or goes
// past the boundary we're interested in
do {
containerElement.insertBefore(workingNode, workingNode.previousSibling);
workingRange.moveToElementText(workingNode);
} while ( (comparison = workingRange.compareEndPoints(
workingComparisonType, textRange)) > 0 && workingNode.previousSibling);
// We've now reached or gone past the boundary of the text range we're
// interested in so have identified the node we want
boundaryNode = workingNode.nextSibling;
if (comparison == -1 && boundaryNode) {
// This must be a data node (text, comment, cdata) since we've overshot.
// The working range is collapsed at the start of the node containing
// the text range's boundary, so we move the end of the working range
// to the boundary point and measure the length of its text to get
// the boundary's offset within the node
workingRange.setEndPoint(isStart ? "EndToStart" : "EndToEnd", textRange);
boundaryPosition = {
node: boundaryNode,
offset: workingRange.text.length
};
} else {
// We've hit the boundary exactly, so this must be an element
boundaryPosition = {
node: containerElement,
offset: getChildIndex(workingNode)
};
}
// Clean up
workingNode.parentNode.removeChild(workingNode);
return boundaryPosition;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<b><div id="testResult"></div></b>
<div id="hoverText"> <p><span class="kinovar"><span id="selection_index3337" class="selection_index"></span>По f7-мъ часЁ твори1тъ сщ7eнникъ начaло съ кади1ломъ и3 со свэщeю, цrкимъ двeремъ tвeрз?ннымъ, и3 поeтъ: Х</span>rт0съ воскRсе: <span class="kinovar">со ст?хи2. И# по ст?сёхъ pал0мъ: Б</span>лгcви2 душE моS гDа: <span class="kinovar">И# ?3ктен?A. Тaже каfjсма nбhчнаz.</span> </p> <div class="slavic"><p><span id="selection_index3737" class="selection_index"></span>(л. рo7з ?б.)</p> <p><span class="kinovar"><span id="selection_index3738" class="selection_index"></span>Во вт0рникъ вeчера</span></p> <p><span class="kinovar"><span id="selection_index3739" class="selection_index"></span>tдaн?е прaздника пaсхи.</span></p><p><span class="kinovar"><span id="selection_index3740" class="selection_index"></span>По f7-мъ часЁ твори1тъ сщ7eнникъ начaло съ кади1ломъ и3 со свэщeю, цrкимъ двeремъ tвeрз?ннымъ, и3 поeтъ: Х</span>rт0съ воскRсе: <span class="kinovar">сост?хи2. И# по ст?сёхъ pал0мъ: Б</span>лгcви2 душE моS гDа: <span class="kinovar">И# ?3ктен?A. Тaже каfjсма nбhчнаz.</span> </p><p><span class="kinovar"><span id="selection_index3741" class="selection_index"></span>На ГDи воззвaхъ: поeмъ ст?хи6ры самоглaсны, слэпaгw, на ?7. Глaсъ в7:</span> </p><p><span class="kinovar"><span id="selection_index3742" class="selection_index"></span>С</span>лэпhй роди1выйсz, въ своeмъ п0мыслэ глаг0лаше: ?3дA ?зъ грBхъ рaди роди1тельныхъ роди1хсz без8 ?ч?ю; (л. рo7и) ?3дA ?зъ за невёр?е kзhкwвъ роди1хсz во ?бличeн?е; не домышлsюсz вопрошaти: когдA н0щь, когдA дeнь; не терпи1та ми2 н0зэ кaменнагw претыкaн?z, не ви1дэхъ сlнца с?sюща, нижE во ?бразэ менE создaвшагw. но молю1 ти сz хrтE б9е, при1зри на мS, и3 поми1луй мS.</p></div></div>
回答by Guilherme Ferreira
Aw yiss! Here is ho!
噢耶!这里是 ho!
Simple as it is and whitout Jqueryor any other framework Fiddle: https://jsfiddle.net/703c96dr/
很简单,没有Jquery或任何其他框架 Fiddle:https: //jsfiddle.net/703c96dr/
It will put spans on each word and add a onmouseover and onomouseout function. I could create a simple class to make it more usable but the code is so simple that anyone can edit and use.
它将在每个单词上放置跨度并添加 onmouseover 和 onomouseout 功能。我可以创建一个简单的类以使其更有用,但代码非常简单,任何人都可以编辑和使用。
<p>This is my text example of word highlighting or, if you want, word hovering</p>
<p>This is another text example of word highlighting or, if you want, word hovering</p>
Simple code
简单的代码
function onmouseoverspan(){
this.style.backgroundColor = "red";
}
function onmouseoutspan(){
this.style.backgroundColor = "transparent";
}
var spans,p = document.getElementsByTagName("p");
for(var i=0;i<p.length;i++) {
if(p[i]==undefined) continue;
p[i].innerHTML = p[i].innerHTML.replace(/\b(\w+)\b/g, "<span></span>");
spans = p[i].getElementsByTagName("span")
for(var a=0;a<spans.length;a++) {
spans[a].onmouseover = onmouseoverspan;
spans[a].onmouseout = onmouseoutspan;
}
}
回答by Eyal
In Firefox you can hook the mousemove event. The callback has one argument, e. In the callback, do this:
在 Firefox 中,您可以挂钩 mousemove 事件。回调有一个参数,例如。在回调中,执行以下操作:
var range = HTTparent.ownerDocument.createRange();
range.selectNode(e.rangeParent);
var str = range.toString();
range.detach();
Now str has the entire text that the mouse was over. e.rangeOffset is the location of the mousepointer within that string. In your case, str would be "some long text" and e.rangeOffset would be 11 if you were over the "e" in "text".
现在 str 具有鼠标悬停的整个文本。e.rangeOffset 是该字符串中鼠标指针的位置。在您的情况下, str 将是“一些长文本”,如果您在“文本”中的“e”上方,则 e.rangeOffset 将是 11。
This code will get a little confused if you are in the margins, for instance when the mouse pointer is on the same line as the text but after the end of it. To fix this, you need to check that you are actually on top of text. Here's the test:
如果您在页边空白处,则此代码会有些混乱,例如,当鼠标指针与文本在同一行但在文本末尾之后时。要解决此问题,您需要检查您是否确实位于文本之上。这是测试:
if(e && e.rangeParent && e.rangeParent.nodeType == e.rangeParent.TEXT_NODE
&& e.rangeParent.parentNode == e.target)
This technique works in Firefox. Doesn't work in Chrome.
这种技术适用于 Firefox。在 Chrome 中不起作用。
回答by amphetamachine
You would probably have to break up the paragraph so that each word was contained inside of its own separate <span> element and then add onmouseoverevent attributes to each of them.
您可能必须拆分段落,以便每个单词都包含在其自己单独的 <span> 元素中,然后为每个单词添加onmouseover事件属性。
..And I think you mean "<p>some long text</p>"; backslashes are not part of HTML.
..我认为你的意思是“<p>一些长文本</p>”;反斜杠不是 HTML 的一部分。

