JavaScript를 사용하여 커서 아래에 단어를 가져 오는 방법은 무엇입니까?
예를 들어 내가 가지고 있다면
<p> some long text </p>
내 HTML 페이지에서 마우스 커서가 예를 들어 '텍스트'라는 단어 위에 있는지 어떻게 알 수 있습니까?
다른 두 가지 답변 외에도 jQuery (또는 일반적으로 자바 스크립트)를 사용하여 단락을 범위로 분할 할 수 있습니다.
이렇게하면 단어 주위에 범위가있는 텍스트를 출력하는 것에 대해 생각할 필요가 없습니다. 당신의 자바 스크립트가 당신을 위해 그것을하게하십시오.
예 :
<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>$1</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>
위의 코드는 작동하는 동안 단락 태그 내의 모든 html을 제거합니다.
내 다른 대답은 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);
}
mousemove 핸들러에서 getWordAtPoint(e.target, e.x, e.y);
전문:
단어 (또는 단어의 문자)를 구분하는 여러 범위와 중첩 된 HTML이있는 경우 위의 모든 솔루션은 완전하고 올바른 단어를 반환하는 데 문제가 있습니다.
다음은 현상금 질문의 예입니다 Х</span>rт0съ
. 제대로 반환하는 방법 Хrт0съ
? 이러한 문제는 2010 년에 해결되지 않았으므로 이제 두 가지 해결책을 제시하겠습니다 (2015).
해결 방법 1-내부 태그를 제거하고 각 전체 단어를 감싸십시오.
한 가지 해결책은 단락 내의 span 태그를 제거하고 해당 텍스트는 유지하는 것입니다. 따라서 분할 된 단어와 구는 일반 텍스트로 다시 결합됩니다. 각 단어는 공백이 아닌 공백으로 구분되며, 해당 단어는 개별적으로 액세스 할 수있는 범위로 래핑됩니다.
데모에서 전체 단어를 강조 표시하여 전체 단어의 텍스트를 얻을 수 있습니다.
암호:
$(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, "$1<span>$2</span>");
newText = newText.replace(/^([^\s]+)/g, "<span>$1</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>
솔루션 1 전체 텍스트 데모
솔루션 2-캐럿 검사 및 DOM 탐색 :
여기에 더 정교한 솔루션이 있습니다. 텍스트 노드의 커서 아래에있는 전체 및 올바른 단어를 정확하게 캡처하는 노드 탐색을 사용하는 알고리즘 솔루션입니다.
캐럿 위치를 확인하여 임시 단어 를 찾습니다 ( caretPositionFromPoint
또는 caretRangeFromPoint
, @chrisv에 대한 아이디어에 대한 크레딧 사용 ). 이것은 전체 단어 일 수도 있고 아닐 수도 있습니다.
그런 다음 텍스트 노드 (시작 또는 끝)의 가장자리에 있는지 확인하기 위해 분석됩니다. 그렇다면 이전 텍스트 노드 또는 다음 텍스트 노드를 검사하여이 단어 조각을 더 길게 만들기 위해 결합해야하는지 확인합니다.
예:
Х</span>rт0съ
반환 Хrт0съ
하지 Х
않아야 rт0съ
합니다.
DOM 트리는 다음 비 장벽 텍스트 노드를 얻기 위해 순회됩니다. 두 단어 조각이 하나 <p>
또는 다른 장벽 태그 로 분리되면 인접하지 않으므로 동일한 단어의 일부가 아닙니다.
예:
њб.)</p><p>Во
돌아 오지 말아야한다 њб.)Во
데모에서 왼쪽 부동 div는 커서 아래에있는 단어입니다. 오른쪽 부동 div (표시되는 경우)는 경계의 단어가 어떻게 형성되었는지 보여줍니다. 다른 태그는이 솔루션의 텍스트와 함께 안전하게 인라인 될 수 있습니다.
암호:
$(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>
( 참고 : 텍스트 노드 테두리의 위치를 밝히기 위해 샘플 HTML에있는 span 태그에 스타일을 자유롭게 적용했습니다.)
솔루션 2 전체 텍스트 데모
(지금까지 Chrome과 IE에서 작업 중입니다. IE의 경우 브라우저 간 호환성을 위해 IERange 의 메서드를 shim으로 사용해야했습니다.)
내 지식으로는 할 수 없습니다.
내가 생각할 수있는 유일한 것은 각 단어를 자체 요소에 넣은 다음 해당 요소에 이벤트 위에 마우스를 적용하는 것입니다.
<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>
현재 CSSOM보기 초안 에는 이에 대한 API가 있습니다 .document.caretPositionFromPoint(x,y)
하지만 어떤 브라우저가이를 지원하는지 확인해야합니다. Firefox 7은이를 전혀 지원하지 않는 것으로 보이지만 버그 보고서에 따르면 Firefox 9는 지원할 것입니다. Chrome 14 caretRangeFromPoint(x,y)
는 본질적으로 동일하지만 이전 CSSOM 초안을 지원합니다.
다음은 현상금에 대한 해결책입니다.
chrisv가 제안한대로 document.caretRangeFromPoint
(chrome) 또는 document.caretPositionFromPoint
(Firefox)를 사용할 수 있습니다 . 이 솔루션은 텍스트 또는 DOM을 변경하지 않으므로 질문에 더 잘 대답한다고 생각합니다.
이 함수는 DOM을 변경하지 않고 마우스 커서 아래에있는 단어를 반환합니다.
로부터 document.caretRangeFromPoint
문서 :
Document 인터페이스의 caretRangeFromPoint () 메서드는 지정된 좌표 아래의 문서 조각에 대한 Range 개체를 반환합니다.
로부터 document.caretPositionFromPoint
문서 :
이 메서드는 두 좌표를 기반으로 문서에서 캐럿 위치를 검색하는 데 사용됩니다. 찾은 DOM 노드와 해당 노드의 문자 오프셋을 포함하는 CaretPosition이 반환됩니다.
두 함수는 약간 다르지만 둘 다 텍스트를 포함하는 노드와이 텍스트에서 커서의 오프셋을 반환합니다. 따라서 마우스 아래에서 단어를 쉽게 얻을 수 있습니다.
전체 예보기 :
$(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>
다음은 대부분의 경우 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;
}
나는 구두점을 걸러 내고 하이픈이 붙은 단어를 독자에게 연습으로 적절하게 처리합니다. :).
어이! 여기 호!
간단하고 Jquery 또는 다른 프레임 워크 Fiddle : https://jsfiddle.net/703c96dr/
각 단어에 범위를두고 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>
간단한 코드
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>$1</span>");
spans = p[i].getElementsByTagName("span")
for(var a=0;a<spans.length;a++) {
spans[a].onmouseover = onmouseoverspan;
spans[a].onmouseout = onmouseoutspan;
}
}
각 단어가 별도의 <span> 요소 안에 포함되도록 단락을 분할 한 다음 각 단어에 onmouseover
이벤트 속성을 추가 해야 할 것입니다.
.. 그리고 "<p> 긴 글 </ p>"을 의미한다고 생각합니다. 백 슬래시는 HTML의 일부가 아닙니다.
Firefox에서는 mousemove 이벤트를 연결할 수 있습니다. 콜백에는 하나의 인수 e가 있습니다. 콜백에서 다음을 수행하십시오.
var range = HTTparent.ownerDocument.createRange();
range.selectNode(e.rangeParent);
var str = range.toString();
range.detach();
이제 str에는 마우스가있는 전체 텍스트가 있습니다. e.rangeOffset은 해당 문자열 내에서 mousepointer의 위치입니다. 귀하의 경우 str은 "some long text"이고 e.rangeOffset은 "text"에서 "e"를 넘으면 11이됩니다.
이 코드는 여백에있는 경우 약간 혼란 스러울 것입니다. 예를 들어 마우스 포인터가 텍스트와 같은 줄에 있지만 끝 뒤에있을 때입니다. 이 문제를 해결하려면 실제로 텍스트 위에 있는지 확인해야합니다. 테스트는 다음과 같습니다.
if(e && e.rangeParent && e.rangeParent.nodeType == e.rangeParent.TEXT_NODE
&& e.rangeParent.parentNode == e.target)
이 기술은 Firefox에서 작동합니다. Chrome에서 작동하지 않습니다.
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
// 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;
}
function onClick(event) {
var elt = document.getElementById('info');
elt.innerHTML = "";
var textNode;
var offset;
// Internet Explorer
if (document.body.createTextRange) {
elt.innerHTML = elt.innerHTML+("*************** IE **************<br/>");
range = document.body.createTextRange();
range.moveToPoint(event.clientX, event.clientY);
range.select();
range = getTextRangeBoundaryPosition(range, true);
textNode = range.node;
offset = range.offset;
elt.innerHTML = elt.innerHTML + "IE ok, result: [" + escapeHtml(textNode.nodeName) + "]/[" + escapeHtml(textNode.textContent) + "] @" + offset + "</br>";
}
// Internet Explorer method 2
if (document.body.createTextRange) {
elt.innerHTML = elt.innerHTML+("*************** IE, Method 2 **************<br/>");
range = document.body.createTextRange();
range.moveToPoint(event.clientX, event.clientY);
range.select();
var sel = document.getSelection();
textNode = sel.anchorNode;
offset = sel.anchorOffset;
elt.innerHTML = elt.innerHTML + "IE M2 ok, result: [" + escapeHtml(textNode.nodeName) + "]/[" + escapeHtml(textNode.textContent) + "] @" + offset + "</br>";
}
// Firefox, Safari
// REF: https://developer.mozilla.org/en-US/docs/Web/API/Document/caretPositionFromPoint
if (document.caretPositionFromPoint) {
elt.innerHTML = elt.innerHTML+("*************** Firefox, Safari **************<br/>");
range = document.caretPositionFromPoint(event.clientX, event.clientY);
textNode = range.offsetNode;
offset = range.offset;
elt.innerHTML = elt.innerHTML + "caretPositionFromPoint ok, result: [" + escapeHtml(textNode.nodeName) + "]/[" + escapeHtml(textNode.textContent) + "] @" + offset + "</br>";
// Chrome
// REF: https://developer.mozilla.org/en-US/docs/Web/API/document/caretRangeFromPoint
}
if (document.caretRangeFromPoint) {
elt.innerHTML = elt.innerHTML+("*************** Chrome **************<br/>");
range = document.caretRangeFromPoint(event.clientX, event.clientY);
textNode = range.startContainer;
offset = range.startOffset;
elt.innerHTML = elt.innerHTML + "caretRangeFromPoint ok, result: [" + escapeHtml(textNode.nodeName) + "]/[" + escapeHtml(textNode.textContent) + "] @" + offset + "</br>";
}
}
document.addEventListener('click', onClick);
#info {
position: absolute;
bottom: 0;
background-color: cyan;
}
<div class="parent">
<div class="child">SPACE SPACE Bacon ipsum dolor amet <span>SPAN SPANTT SPOOR</span> meatball bresaola t-bone tri-tip brisket. Jowl pig picanha cupim SPAXE landjaeger, frankfurter spare ribs chicken. Porchetta jowl pancetta drumstick shankle cow spare ribs jerky
tail kevin biltong capicola brisket venison bresaola. Flank sirloin jowl andouille meatball venison salami ground round rump boudin turkey capicola t-bone. Sirloin filet mignon tenderloin beef, biltong doner bresaola brisket shoulder pork loin shankle
turducken shank cow. Bacon ball tip sirloin ham.
</div>
<div id="info">Click somewhere in the paragraph above</div>
</div>
내 대답은 Drakes의 "Solution 2-Caret Inspection and DOM traversal"에서 파생되었습니다. 이 솔루션을 지적 해 주신 Drakes에게 감사드립니다!
However, there's two problems with Drakes' solution 2 when working on IE. (1) the offset as calculated is incorrect, and (2) too complex, lots of code.
See my demonstration on JSFiddle at here.
For problem 1, if you click somewhere at about the last line of the text, for example somewhere in "shoulder pork loin shankle turducken shank cow. Bacon ball tip sirloin ham.", you can notice the offset calculation is different with IE (original solution) and IE method 2 (my solution). Also, the results from IE method 2 (my solution) and from Chrome, Firefox are the same.
내 솔루션도 훨씬 간단합니다. 트릭은 TextRange를 사용하여 절대 X / Y 위치에서 선택을 한 후 document.getSelection ()을 호출하여 IHTMLSelection 유형을 가져 오는 것입니다. IE <9에서는 작동하지 않지만 괜찮다면이 방법이 훨씬 간단합니다. 또 다른주의 사항은 IE의 경우 메서드의 부작용 (원래 방법과 동일)은 선택 변경 (즉, 사용자의 원래 선택 손실)입니다.
// Internet Explorer method 2
if (document.body.createTextRange) {
elt.innerHTML = elt.innerHTML+("*************** IE, Method 2 **************<br/>");
range = document.body.createTextRange();
range.moveToPoint(event.clientX, event.clientY);
range.select();
var sel = document.getSelection();
textNode = sel.anchorNode;
offset = sel.anchorOffset;
elt.innerHTML = elt.innerHTML + "IE M2 ok, result: [" + escapeHtml(textNode.nodeName) + "]/[" + escapeHtml(textNode.textContent) + "] @" + offset + "</br>";
}
참고 URL : https://stackoverflow.com/questions/2444430/how-to-get-a-word-under-cursor-using-javascript
'code' 카테고리의 다른 글
PhpStorm의 코드 조각 (0) | 2020.10.29 |
---|---|
Notepad ++에서 HTML 태그를 들여 쓰는 방법 (0) | 2020.10.29 |
Mac OS X의 Eclipse에서 파일로 이동하기위한 키보드 단축키는 무엇입니까? (0) | 2020.10.29 |
Firebug에서 "sticky"상태로 마우스를 올릴 수 있습니까? (0) | 2020.10.29 |
반환 값으로 저장 프로 시저 호출 (0) | 2020.10.29 |