2016-05-26 3 views
7

ich ein mouseup Ereignis verwenden eine Funktion auszulösen, den Text hebt und umgibt den markierten Text mit einer Spanne (Funktion von Stack-Überlauf):JS - surround behält nur Highlights auf Text etwa 20% der Highlight versucht

function highlightText(e) { 

    var t = window.getSelection().toString(); 
    if (t) { 
     $("#mySpan").remove(); 
     var range = window.getSelection().getRangeAt(0); 
      newNode = document.createElement("span"); 
     newNode.id = 'mySpan'; 

     range.surroundContents(newNode); 

    } 
} 

Das Hauptproblem, auf das ich stoße, ist, dass, solange surroundContents enthalten ist, der Text nur etwa 20% der Highlight-Versuche hervorgehoben bleibt (andernfalls wird die Hervorhebung sofort ausgeblendet). Ich habe versucht, ein SetTimeout, nicht aufrufen Surround-Content für 1s. Ich habe auch versucht, die remove() -Anweisung zu entfernen, aber immer noch nicht gut.

Irgendwelche Ideen, warum das passiert?

+0

was ist mit dem Starten der Funktion mit 'e.preventDefault();' –

+0

Ich habe dies direkt nach und vor surroundContents Anruf, aber ohne Erfolg. –

+0

Haben Sie versucht, "TextHighlighter" von [hier] (https://www.sitepoint.com/10-jquery-text-highlighter-plugins/) zu verwenden? – dude

Antwort

1

Die wahrscheinliche Ursache für den Fehler ist, dass der ausgewählte Text nur den Anfang oder das Ende eines Nicht-Text-Knotens umfasst und nicht beide.

So waren, wenn nur diesen Code auszuführen Auswahl „Das ist Bo“ in dem folgende es scheitern wird (und eine Ausnahme auslösen), weil es nicht auch den schließenden Tag in der Auswahl nicht erfassen:

This is <em>bold</em> 

endet also nach oben mit:

This is <em>bo 

Referenz: https://developer.mozilla.org/en-US/docs/Web/API/Range/surroundContents

2

ich das gleiche Problem mit Chrom auf Android zugewandt wurde. In einigen speziellen Fällen würde der Aufruf von range.surroundContents(newNode) ein sehr seltsames Verhalten beim erneuten Laden der Seite verursachen. Nach Überprüfung the documentation of the function:

Dieses Verfahren ist nahezu äquivalent zu newNode.appendChild (range.extractContents()); Bereich.insertNode (neuer Knoten). Nach der Umgrenzung umfassen die Grenzpunkte von den Bereich newNode.

So war die offensichtliche Sache, einen anderen Weg anzuwenden, markieren Sie den Text. Ich fand mark.js Bibliothek, die genau das tat, was ich ohne diese lästige Nebenwirkung wollte. (Hier ist eine JSFiddle sample, die zeigt, wie es verwendet wird, um nur die Auswahl zu markieren). Der Unterschied besteht darin, dass die Bibliothek range.surroundContents(newNode) und newNode.appendChild nicht verwendet, sondern node.replaceChild.

Darauf basierend, hier ist die Lösung für das Problem, das ich hatte und ich denke, es gilt auch für Ihren Fall.

function surroundRangeWithSpan(range) { 
    var span = document.createElement('span'); 

    // The text is within the same node (no other html elements inside of it) 
    if (range.startContainer.isEqualNode(range.endContainer) && range.startContainer.childNodes.length == 0) { 
     // Here you customise your <span> element 
     customSurroundContents(range, span); 
    } else { 
     // Here you have to break the selection down 
    } 
    return span; 
    } 

    function customSurroundContents(range, span) { 
    var node = range.commonAncestorContainer; 
    var startNode = node.splitText(range.startOffset); 
    var ret = startNode.splitText(range.toString().length); 
    span.textContent = startNode.textContent; 
    startNode.parentNode.replaceChild(span, startNode); 
    } 

Und Sie übergeben window.getSelection().getRangeAt(0) an die Funktion.

Verwandte Themen