Lassen Sie sich Text und ausgewählten Knoten auf einer Seite ausgewählt?
-
21-08-2019 - |
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?
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.
Sie können starten wollen von http: //javascript.internet .com / page-details / copy-selected-text.html
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));