2010-11-18 7 views
7

Bei der Auswahl von Texten in HTML-Dokumenten kann von einem DOM-Element zu einem anderen Element übergegangen werden, wobei möglicherweise mehrere andere Elemente auf dem Weg übergeben werden. Mit der DOM-API ist es möglich, den Bereich der Auswahl, die ausgewählten Texte und sogar das Elternelement aller ausgewählten DOM-Elemente zu erhalten (mit commonAncestorContainer oder parentElement() basierend auf dem verwendeten Browser). Ich bin mir jedoch nicht bewusst, dass alle Elemente, die Elemente der ausgewählten Texte enthalten, aufgelistet werden können, außer dass das einzige übergeordnete Element abgerufen wird, das alle Elemente enthält. Das Verwenden der Eltern und Durchlaufen der Kinderknoten wird es nicht tun, da es möglicherweise andere Geschwister gibt, die in diesem Elternelement nicht ausgewählt werden.Alle DOM-Blockelemente für ausgewählte Texte abrufen

Also, gibt es eine Möglichkeit, dass ich alle diese Elemente, die die ausgewählten Texte enthält, bekommen kann. Ich bin hauptsächlich daran interessiert, die Blockelemente zu erhalten (p, h1, h2, h3, ... etc), aber ich glaube, wenn es einen Weg gibt, alle Elemente zu bekommen, dann kann ich sie durchgehen und sie filtern, um das zu bekommen, was ich wollen. Ich freue mich über Ideen und Anregungen.

Vielen Dank.

Antwort

16

Key ist window.getSelection().getRangeAt(0)https://developer.mozilla.org/en/DOM/range

Hier einige Beispiel-Code, die Sie mit spielen können, zu tun, was Sie wollen. Erwähnen Sie, was Sie wirklich in Frage wünschen, wird Menschen helfen, bessere Antworten zu geben.

var selection = window.getSelection(); 
var range = selection.getRangeAt(0); 
var allWithinRangeParent = range.commonAncestorContainer.getElementsByTagName("*"); 

var allSelected = []; 
for (var i=0, el; el = allWithinRangeParent[i]; i++) { 
    // The second parameter says to include the element 
    // even if it's not fully selected 
    if (selection.containsNode(el, true)) { 
    allSelected.push(el); 
    } 
} 


console.log('All selected =', allSelected); 

Dies ist nicht die effizienteste Art und Weise, können Sie den DOM selbst mit der startContainer/endContainer der Strecke durchqueren, zusammen mit nextSibling/previousSibling und childnodes.

+0

Nicht die perfekte Lösung, wie Sie gesagt haben, aber es gab mir eine Idee, wie es geht. Daher wählte ich dies als die richtigste Antwort auf meine Bedürfnisse. Schätze das wirklich. – cria

+0

Dies ist eine anständige Antwort, wird aber nicht in IE <9 funktionieren. Es könnte mit einer Überprüfung, dass die Auswahl vor dem Aufruf von 'selection.getRangeAt (0); auch vorhanden ist (mit der Eigenschaft 'rangeCount' der Auswahl ist am einfachsten). –

+0

Es gibt viele Fehler, die ich nicht angesprochen habe, das ist nur, um in die richtige Richtung zu gehen. Ihre Bibliothek benötigt 22k unkomprimiertes Javascript, um wirklich damit umzugehen, und wenn ich es brauchte, würde ich das einfach benutzen. –

0

Es klingt, als könnten Sie Traversing from the jQuery API verwenden.

Möglicherweise .contents()

Hoffnung, das hilft!

+0

Ja, die Methoden dort sind alle großartig. Aber ich glaube nicht, dass ich den vom Browser ausgewählten Textbereich als Eingabe für diese Methoden verwenden kann, oder? oder vielleicht fehlt mir etwas ... Danke – cria

10

Sie können meine Rangy library verwenden, um dies zu tun. Es bietet eine Implementierung von DOM Range and Selection-Objekten für alle Browser, einschließlich IE, und verfügt über zusätzliche Range-Methoden. Eines davon ist getNodes():

function isBlockElement(el) { 
    // You may want to add a more complete list of block level element 
    // names on the next line 
    return /h[1-6]|div|p/i.test(el.tagName); 
} 

var sel = rangy.getSelection(); 
if (sel.rangeCount) { 
    var range = sel.getRangeAt(0); 
    var blockElements = range.getNodes([1], isBlockElement); 
    console.log(blockElements); 
} 
+0

Ich habe keinen Zweifel, dass dieser Code der genaueste ist. Aber die Verwendung Ihrer lib ist ein Overkill für meinen Fall aufgrund der großen Größe der lib. Daher wählte ich die andere Antwort, obwohl es einige Probleme gibt, die ich behandeln muss. Wenn es eine Wahl gäbe, zwei Antworten auszuwählen, würde ich sicherlich auch Ihre markieren. Halten Sie die große lib/Arbeit :) – cria

+0

@crija: Fair genug. Was Sie mit mir bekommen, ist die Unterstützung für IE. –

+3

@TimDown danke für deine Arbeit an Rangy. Es macht eine Reihe von komplizierten Problemen viel einfacher. –