81 Stimmen

Wie bekomme ich mit JavaScript ein Wort unter den Cursor?

Wenn ich zum Beispiel Folgendes habe

<p> some long text </p>

Wie kann ich auf meiner HTML-Seite wissen, dass sich der Mauszeiger zum Beispiel über dem Wort "Text" befindet?

1 Stimmen

Dies ist eine Live-Demo für wie man mit JavaScript ein Wort unter den Cursor bringt auf der Grundlage des Quellcodes, der von Damovisa : jsfiddle.net/5gyRx .

2 Stimmen

@Ivan Es gibt eine neue Antwort auf diese Frage von einem Bounty. Sie könnten in Erwägung ziehen, sie auszuwählen (im Interesse neuer Benutzer, die kommen).

5voto

chrisv Punkte 1322

Es gibt eine API für diese Funktion in der aktuellen CSSOM Ansichtsentwurf : document.caretPositionFromPoint(x,y)

Sie müssen jedoch prüfen, welcher Browser dies unterstützt. Firefox 7 scheint es überhaupt nicht zu unterstützen, während Fehlerberichte darauf hindeuten, dass Firefox 9 es unterstützt. Chrome 14 unterstützt caretRangeFromPoint(x,y) der im Wesentlichen derselbe ist, aber aus einem älteren CSSOM-Entwurf stammt.

0 Stimmen

Es sieht so aus, als würde Ihre Antwort zu meinem Kopfgeld für das Projekt passen. Es braucht nur ein bisschen Arbeit, um das Wort tatsächlich vom Caret-Punkt aus erweitert zu finden. Die nativen Bereich erweitern Methode funktioniert nicht gut genug. Ich kann dies selbst erforschen, aber wenn Sie Code zur Verfügung stellen können, um mit meiner Demo zu arbeiten jsfiddle.net/ohaf4ytL Das wäre großartig.

0 Stimmen

@user1122069 Ich habe diese Lösung implementiert ( stackoverflow.com/a/30606508/2576706 ). Entspricht es Ihren Bedürfnissen?

5voto

Ludovic Feltz Punkte 10775

Hier ist die Lösung für das Kopfgeld.

Wie vorgeschlagen von chrisv können Sie document.caretRangeFromPoint (Chrom) oder document.caretPositionFromPoint (Firefox). Ich denke, diese Lösung beantwortet Ihre Frage besser, da sie Ihren Text oder das DOM nicht verändert.

Diese Funktion gibt das Wort unter dem Mauszeiger zurück, ohne das DOM zu verändern:

Von der document.caretRangeFromPoint Dokumentation :

Die Methode caretRangeFromPoint() der Document-Schnittstelle gibt ein Range-Objekt für das Dokumentfragment unter den angegebenen Koordinaten zurück.

Von der document.caretPositionFromPoint Dokumentation :

Mit dieser Methode wird die Caret-Position in einem Dokument anhand von zwei Koordinaten ermittelt. Es wird eine CaretPosition zurückgegeben, die den gefundenen DOM-Knoten und den Zeichenversatz in diesem Knoten enthält.

Die beiden Funktionen unterscheiden sich geringfügig, geben aber beide den Knoten zurück, der den Text enthält, sowie den Offset des Cursors in diesem Text. So ist es einfach, das Wort unter der Maus zu finden.

Siehe das vollständige Beispiel:

$(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 te, 3 e: </span>r0 R: <span class="kinovar"> 2. #   p0: </span>c2 E S D: <span class="kinovar"># 3A. a fj nhz.</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>ta 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 te, 3 e: </span>r0 R: <span class="kinovar">2. #   p0: </span>c2 E S D: <span class="kinovar"># 3A. a fj nhz.</span> </p><p><span class="kinovar"><span id="selection_index3741" class="selection_index"></span> D a: e 6 a, aw,  7. a 7:</span> </p><p><span class="kinovar"><span id="selection_index3742" class="selection_index"></span></span>h 1z,  e 0 0: 3A  B a 1 1z 8 ; (. o7) 3A    khw 1z  e;  sz a: A 0, A e;  1 2 0 aw az,  1 l s, E   E aw.  1  z rE 9, 1  S, 3 1 S.</p></div></div>

0 Stimmen

"Holen Sie sich das HTML in #hoverText - nur ein Wrapper für die Bequemlichkeit" - sieht vertraut aus

0 Stimmen

@Drakes Ich habe alle Antworten hier gelesen und fand deine Idee, den Text in ein div einzuschließen, gut, also habe ich denselben Namen beibehalten. Aber der Code danach ist völlig anders :)

0 Stimmen

@Drakes Übrigens fand ich deine Lösung sehr gut. Viel Glück für das Kopfgeld ;)

3voto

Guilherme Ferreira Punkte 2081

Oh, ja! Hier ist ho!

So einfach wie es ist und ohne Jquery oder einem anderen Rahmen Fiddle: https://jsfiddle.net/703c96dr/

Es wird jedes Wort mit einem Abstand versehen und eine Onmouseover- und Onmouseout-Funktion hinzufügen. Ich könnte eine einfache Klasse erstellen, um es besser nutzbar zu machen, aber der Code ist so einfach, dass jeder ihn bearbeiten und verwenden kann.

<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>

Einfacher 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>$1</span>");
    spans = p[i].getElementsByTagName("span")
    for(var a=0;a<spans.length;a++) {
        spans[a].onmouseover = onmouseoverspan;
        spans[a].onmouseout = onmouseoutspan;
    }
}

2voto

amphetamachine Punkte 24877

Wahrscheinlich müssten Sie den Absatz so aufteilen, dass jedes Wort in einem eigenen <span>-Element enthalten ist, und dann Folgendes hinzufügen onmouseover Ereignisattribute zu jedem von ihnen.

und ich denke, Sie meinen "<p>ein langer Text</p>"; Backslashes sind nicht Teil von HTML.

2voto

Eyal Punkte 5478

In Firefox können Sie das Mousemove-Ereignis aktivieren. Der Callback hat ein Argument, e. In dem Callback tun Sie Folgendes:

var range = HTTparent.ownerDocument.createRange();
range.selectNode(e.rangeParent);
var str = range.toString();
range.detach();

Jetzt enthält str den gesamten Text, über dem sich die Maus befand. e.rangeOffset ist die Position des Mauszeigers innerhalb dieser Zeichenfolge. In Ihrem Fall wäre str "some long text" und e.rangeOffset wäre 11, wenn Sie über dem "e" in "text" wären.

Dieser Code kommt etwas durcheinander, wenn Sie sich in den Rändern befinden, z. B. wenn sich der Mauszeiger auf derselben Zeile wie der Text befindet, aber nach dem Ende des Textes. Um dies zu beheben, müssen Sie überprüfen, ob Sie sich tatsächlich über dem Text befinden. Hier ist der Test:

if(e && e.rangeParent && e.rangeParent.nodeType == e.rangeParent.TEXT_NODE
   && e.rangeParent.parentNode == e.target)

Diese Technik funktioniert in Firefox. Funktioniert nicht in Chrome.

0 Stimmen

Danke, Mann, das hat mir sehr geholfen. Sobald Sie sowohl in Chrome als auch in Firefox Reichweite haben, können Sie die range.offsetNode || range.startContainer als die rangeParentNode und es funktioniert auch für Chromium-basierte Engines.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X