Entry
How can I loop through elements contained in a text selection in Mozilla/Firefox/Netscape 7?
How can I loop through elements contained in a text selection in Mozilla/Firefox/Netscape 7?
How can I loop through elements contained in a text selection in Mozilla/Firefox/Netscape 7?
Nov 16th, 2004 05:24
Martin Honnen,
Mozilla (and Mozilla based browsers like Netscape 7, Firefox) expose the
text selection as an object returned by
window.getSelection()
which implements the nsISelection interface
http://xulplanet.com/references/xpcomref/ifaces/nsISelection.html
That interfaces mainly exposes the selection as a W3C DOM Level 2 range
object (In Western languages as far as I understand the selection can
only contain exactly one range while for other languages there might be
several ranges in the selection. This article deals only with one range
in the selection.):
http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html
but ranges in Mozilla have some additional properties and methods as
documented here:
http://lxr.mozilla.org/seamonkey/source/dom/public/idl/range/nsIDOMNSRange.idl
If you want to loop through the elements contained in a selection then
one approach to do that is to use the commonAncestorContainer of the
range in the selection, call getElementsByTagName('tagname') on it and
loop through the returned node list to check whether the element nodes
are contained in the range:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>traversing the nodes in a text selection in Mozilla</title>
<script type="text/javascript">
function getElementsInSelection (tagName) {
var elements = null;
var range;
var selection;
if (window.getSelection) {
selection = window.getSelection();
elements = new Array();
if (selection.rangeCount > 0) {
range = selection.getRangeAt(0);
var elementsToCheck =
range.commonAncestorContainer.getElementsByTagName(tagName);
for (var i = 0; i < elementsToCheck.length; i++) {
var elementToCheck = elementsToCheck[i];
if (range.compareNode(elementToCheck) == range.NODE_INSIDE) {
elements.push(elementToCheck);
}
}
}
}
return elements;
}
</script>
<script type="text/javascript">
function listElementsInSelection (tagName) {
clearOutput();
var elements = getElementsInSelection(tagName);
if (elements) {
output('Found ' + elements.length + ' elements with tagName ' +
tagName + ' in the selection:');
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
var text = '';
text += (i + 1) + ': ';
text += 'tagName: ' + element.tagName + '; ';
text += 'textContent: ' + getTextContent(element);
output(text);
}
}
else {
output('nsISelection not supported.');
}
}
function output (text) {
var outputDiv = document.getElementById('output');
outputDiv.appendChild(document.createTextNode(text));
outputDiv.appendChild(document.createElement('br'));
}
function clearOutput () {
var outputDiv = document.getElementById('output');
while (outputDiv.hasChildNodes()) {
outputDiv.removeChild(outputDiv.lastChild);
}
}
function getTextContent (node) {
if (typeof node.textContent != 'undefined') {
return node.textContent;
}
else if (node.nodeType == 3) {
return node.nodeValue;
}
else {
var textContent = '';
for (var i = 0; i < node.childNodes.length; i++) {
textContent += getTextContent(node.childNodes[i]);
}
return textContent;
}
}
</script>
</head>
<body>
<div>
<p>This is some <i>text</i> to select and then test the <i>code</i>.
Kibology for all. <b>All</b> for Kibology.</p>
</div>
<div>
<input type="button" value="list all i elements in the selection"
onclick="listElementsInSelection('i');">
<input type="button" value="list all elements in the selection"
onclick="listElementsInSelection('*');">
</div>
<div id="output"></div>
</body>
</html>
The code has been tested with Netscape 7.2 and Firefox 1.0 and should
work with any Mozilla 1.0 or later browser.