I want to get all of the elements in a user highlighted area. The problem is that I don't know how to traverse to different parts of the DOM, when the elements are on a different part of the tree. My code so far can only get the elements off the startContainer of the selection range. Do I need some sort of recursion? Here is my code:
getSelectedElementTags:function()
{
var range, sel, container;
sel = content.window.getSelection();
if (sel.getRangeAt)
{
if (sel.rangeCount > 0)
{
range = sel.getRangeAt(0);
}
}
else
{
range = content.window.createRange();
range.setStart(sel.anchorNode, sel.anchorOffset);
range.setEnd(sel.focusNode, sel.focusOffset);
alert("range created");
}
if (range)
{
container = range["startContainer"];
var elms = container.parentNode.getElementsByTagName("*");
elmlist = "parent: "+container.parentNode.tagName + " (" + elms.length + ")\n";
for (i in elms)
{
if (elms[i].tagName != null)
{
elmlist += elms[i].tagName+"\n";
}
}
alert(elmlist);
}
},
You could use a TreeWalker using document.createTreeWalker. An example is below. It lists all elements that are partially or fully selected. You can easily change the behaviour by modifying the parameters passed to document.createTreeWalker.
Note that in Firefox you don't need to check for the existence of the getRangeAt method of a selection. This check is only required for older versions of WebKit. Also, IE < 9 does not support TreeWalker or Range, so the following won't work in those browsers.
Edit Fixed as per comments below.
function rangeIntersectsNode(range, node) {
var nodeRange;
if (range.intersectsNode) {
return range.intersectsNode(node);
} else {
nodeRange = node.ownerDocument.createRange();
try {
nodeRange.selectNode(node);
} catch (e) {
nodeRange.selectNodeContents(node);
}
return range.compareBoundaryPoints(Range.END_TO_START, nodeRange) == -1 &&
range.compareBoundaryPoints(Range.START_TO_END, nodeRange) == 1;
}
}
function getSelectedElementTags(win) {
var range, sel, elmlist, treeWalker, containerElement;
sel = win.getSelection();
if (sel.rangeCount > 0) {
range = sel.getRangeAt(0);
}
if (range) {
containerElement = range.commonAncestorContainer;
if (containerElement.nodeType != 1) {
containerElement = containerElement.parentNode;
}
treeWalker = win.document.createTreeWalker(
containerElement,
NodeFilter.SHOW_ELEMENT,
function(node) { return rangeIntersectsNode(range, node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; },
false
);
elmlist = [treeWalker.currentNode];
while (treeWalker.nextNode()) {
elmlist.push(treeWalker.currentNode);
}
console.log(elmlist);
}
}
<input type="button" onclick="getSelectedElementTags(window)" value="Get selected elements">
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With