Frage

Wenn Sie einen Textblock auszuwählen (möglicherweise über viele DOM-Knoten Spanning) ist es möglich, den markierten Text und Knoten mit Javascript zu extrahieren?

Stellen Sie sich vor diesen HTML-Code:

<h1>Hello World</h1><p>Hi <b>there!</b></p>

Wenn der Benutzer ein mouseDown- Ereignis beim Start initiiert „World ...“ und dann einem mouseUp sogar direkt nach „da!“, Ich bin die Hoffnung, es würde zurückgeben:

Text : { selectedText: "WorldHi there!" },
Nodes: [ 
  { node: "h1", offset: 6, length: 5 }, 
  { node: "p", offset: 0, length: 16 }, 
  { node: "p > b", offset: 0, length: 6 } 
]

Ich habe versucht, den HTML-Code in ein Textfeld setzen, aber das wird kommen mir nur die SelectedText. Ich habe nicht das <canvas> Element versucht, aber das kann eine weitere Option sein.

Wenn kein JavaScript, gibt es eine Möglichkeit, dies ist möglich, eine Firefox-Erweiterung, mit?

War es hilfreich?

Lösung

Sie sind für eine holprige Fahrt, aber das ist durchaus möglich. Das Hauptproblem ist, dass IE und W3C völlig unterschiedliche Schnittstellen, um eine Auswahl zu, so, wenn Sie Cross-Browser-Funktionalität wollen, dann müssen Sie im Grunde zweimal die ganze Sache schreiben. Auch einige grundlegende Funktionalität von beiden Schnittstellen fehlen.

Mozilla-Entwickler-Verbindung hat die Geschichte auf W3C Auswahlen . Microsoft hat ihr System auf MSDN dokumentiert. Ich empfehle, bei PPK Einführung beginnen zu Bereichen .

Hier sind einige grundlegende Funktionen, die ich mit der Arbeit glauben:

// selection objects will differ between browsers
function getSelection () {
  return ( msie ) 
    ? document.selection
    : ( window.getSelection || document.getSelection )();
}

// range objects will differ between browsers
function getRange () {
  return ( msie ) 
      ? getSelection().createRange()
      : getSelection().getRangeAt( 0 )
}

// abstract getting a parent container from a range
function parentContainer ( range ) {
  return ( msie )
      ? range.parentElement()
      : range.commonAncestorContainer;
}

Andere Tipps

Rangy Bibliothek Ihren Teil des Weges dorthin zu gelangen, wird durch die Vereinheitlichung der verschiedenen APIs in IE <9 und alle anderen gängige Browser und durch eine getNodes() Funktion auf seinen Range-Objekten bieten:

function getSelectedNodes() {
    var selectedNodes = [];
    var sel = rangy.getSelection();
    for (var i = 0; i < sel.rangeCount; ++i) {
        selectedNodes = selectedNodes.concat( sel.getRangeAt(i).getNodes() );
    }
    return selectedNodes;
}

, um den ausgewählten Text zu erhalten ist ziemlich einfach, in allen Browsern. In Rangy es ist nur

var selectedText = rangy.getSelection().toString();

Ohne Rangy:

function getSelectedText() {
    var sel, text = "";
    if (window.getSelection) {
        text = "" + window.getSelection();
    } else if ( (sel = document.selection) && sel.type == "Text") {
        text = sel.createRange().text;
    }
    return text;
}

Wie für das Zeichen-Offsets, können Sie so etwas wie dies für jeden Knoten node in der Auswahl tun. Hinweis: Dies ist nicht unbedingt den sichtbaren Text im Dokument dar, da es nicht Rechnung kollabiert Räume nimmt, Text über CSS versteckt, Text außerhalb des normalen Dokumentenfluss über CSS positioniert, Zeilenumbrüche implizierten <br> und Blockelemente sowie andere Feinheiten.

var sel = rangy.getSelection();
var selRange = sel.getRangeAt(0);
var rangePrecedingNode = rangy.createRange();
rangePrecedingNode.setStart(selRange.startContainer, selRange.startOffset);
rangePrecedingNode.setEndBefore(node);
var startIndex = rangePrecedingNode.toString().length;
rangePrecedingNode.setEndAfter(node);
var endIndex = rangePrecedingNode.toString().length;
alert(startIndex + ", " + endIndex);

Dies gibt die ausgewählten Knoten wie ich es verstehe: Wenn ich

<p> ... </p><p> ... </p><p> ... </p><p> ... </p><p> ... </p>...
<p> ... </p><p> ... </p><p> ... </p><p> ... </p><p> ... </p>

eine Menge von Knoten und ich wählen Sie nur ein paar dann will ich nur diese Knoten in der Liste sein.

function getSelectedNodes() {
  // from https://developer.mozilla.org/en-US/docs/Web/API/Selection
  var selection = window.getSelection();
  if (selection.isCollapsed) {
    return [];
  };
  var node1 = selection.anchorNode;
  var node2 = selection.focusNode;
  var selectionAncestor = get_common_ancestor(node1, node2);
  if (selectionAncestor == null) {
    return [];
  }
  return getNodesBetween(selectionAncestor, node1, node2);
}

function get_common_ancestor(a, b)
{
    // from http://stackoverflow.com/questions/3960843/how-to-find-the-nearest-common-ancestors-of-two-or-more-nodes
    $parentsa = $(a).parents();
    $parentsb = $(b).parents();

    var found = null;

    $parentsa.each(function() {
        var thisa = this;

        $parentsb.each(function() {
            if (thisa == this)
            {
                found = this;
                return false;
            }
        });

        if (found) return false;
    });

    return found;
}

function isDescendant(parent, child) {
     // from http://stackoverflow.com/questions/2234979/how-to-check-in-javascript-if-one-element-is-a-child-of-another
     var node = child;
     while (node != null) {
         if (node == parent) {
             return true;
         }
         node = node.parentNode;
     }
     return false;
}

function getNodesBetween(rootNode, node1, node2) {
  var resultNodes = [];
  var isBetweenNodes = false;
  for (var i = 0; i < rootNode.childNodes.length; i+= 1) {
    if (isDescendant(rootNode.childNodes[i], node1) || isDescendant(rootNode.childNodes[i], node2)) {
      if (resultNodes.length == 0) {
        isBetweenNodes = true;
      } else {
        isBetweenNodes = false;
      }
      resultNodes.push(rootNode.childNodes[i]);
    } else if (resultNodes.length == 0) {
    } else if (isBetweenNodes) {
      resultNodes.push(rootNode.childNodes[i]);
    } else {
      return resultNodes;
    }
  };
 if (resultNodes.length == 0) {
    return [rootNode];
  } else if (isDescendant(resultNodes[resultNodes.length - 1], node1) || isDescendant(resultNodes[resultNodes.length - 1], node2)) {
    return resultNodes;
  } else {
    // same child node for both should never happen
    return [resultNodes[0]];
  }
}
https:

Der Code sollte verfügbar sein : //github.com/niccokunzmann/spiele-mit-kindern/blob/gh-pages/javascripts/feedback.js

Ich gab diese Antwort hier, weil ich es hier finden wäre gern.

Es gibt einen viel kürzeren Weg, wenn Sie nur den Bereich wollen.

function getRange(){
    return (navigator.appName=="Microsoft Internet Explorer")
        ? document.selection.createRange().parentElement()
        : (getSelection||document.getSelection)().getRangeAt(0).commonAncestorContainer
}

Alle gängigen Standard-Code, der in IE11 + funktioniert.

Text String

window.getSelection().getRangeAt(0).toString()

Der Startknoten (auch wenn der Text ausgewählt ist, nach hinten):

window.getSelection().anchorNode

Endknoten (selbst wenn der Text ausgewählt ist, rückwärts):

window.getSelection().focusNode

Möchten Sie mehr wissen? Markieren Sie Text und führen Sie den folgenden JavaScript in der Konsole:

console.log(window.getSelection());
console.log(window.getSelection().getRangeAt(0));
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top