reflex wrote:
Hi Reflex,
I have to get every node within range or selection? Is it possible?
In IE, you can only get nodes of type 'element', which would restrict
your requirement. In browsers supporting the W3C Range Model, you could
get to the node level.
Following is some example of the function you are looking for, tested
IE5+, Firefox 2, Opera 9. You may have to filter for the elements
returned by the function, though. Have fun.
HTH,
Elegie.
---
<style type="text/css">
#s1 { border : solid 1px #c00; }
#s2 { border : solid 1px #0c0; }
#s3 { border : solid 1px #00c; }
#result { color : #aaa; margin : 10px; }
</style>
<div id="result"> </div>
<div id="container">
<span id="s1">Old Artist</span>
<span id="s2">Nothing Else</span>
<span id="s3">Skyscraper</span>
</div>
<script type="text/javascript">
function getElementsFromSelection(){
var nodes=null, candidates=[], children, el, parent, rng;
// Main
rng=getSelectionRange();
if(rng) {
parent=getCommonAncestor(rng);
if(parent) {
// adjust from text node to element, if needed
while(parent.nodeType!=1) parent=parent.parentNode;
// obtain all candidates from parent (excluded)
// up to BODY (included)
if(parent.nodeName.toLowerCase()!="body") {
el=parent;
do {
el=el.parentNode;
candidates[candidates.length]=el;
} while(el.nodeName.toLowerCase()!="body");
}
// obtain all candidates down to all children
children=parent.all||parent.getElementsByTagName("*");
for(var j=0; j<children.length; j++)
candidates[candidates.length]=children[j];
// proceed - keep element when range touches it
nodes=[parent];
for(var ii=0, r2; ii<candidates.length; ii++) {
r2=createRangeFromElement(candidates[ii]);
if(r2 && rangeContact(rng, r2))
nodes[nodes.length]=candidates[ii];
}
}
}
return nodes;
// Helpers
function getSelectionRange() {
var rng=null;
if(window.getSelection) {
rng=window.getSelection();
if(rng && rng.rangeCount && rng.getRangeAt) {
rng=rng.getRangeAt(0);
}
} else if(document.selection && document.selection.type=="Text") {
rng=document.selection.createRange();
}
return rng;
}
function getCommonAncestor(rng) {
return rng.parentElement ?
rng.parentElement() : rng.commonAncestorContainer;
}
function rangeContact(r1, r2) {
var p=null;
if(r1.compareEndPoints) {
p={
method:"compareEndPoints",
StartToStart:"StartToStart",
StartToEnd:"StartToEnd",
EndToEnd:"EndToEnd",
EndToStart:"EndToStart"
}
} else if(r1.compareBoundaryPoints) {
p={
method:"compareBoundaryPoints",
StartToStart:0,
StartToEnd:1,
EndToEnd:2,
EndToStart:3
}
}
return p && !(
r2[p.method](p.StartToStart, r1)==1 &&
r2[p.method](p.EndToEnd, r1)==1 &&
r2[p.method](p.StartToEnd, r1)==1 &&
r2[p.method](p.EndToStart, r1)==1
||
r2[p.method](p.StartToStart, r1)==-1 &&
r2[p.method](p.EndToEnd, r1)==-1 &&
r2[p.method](p.StartToEnd, r1)==-1 &&
r2[p.method](p.EndToStart, r1)==-1
);
}
function createRangeFromElement(el) {
var rng=null;
if(document.body.createTextRange) {
rng=document.body.createTextRange();
rng.moveToElementText(el);
} else if(document.createRange) {
rng=document.createRange();
rng.selectNodeContents(el);
}
return rng;
}
};
// Test
window.onload = function(evt) {
setInterval(
function(){
var buf=[];
var nodes=getElementsFromSelection();
if(nodes) {
for(var ii=0; ii<nodes.length; ii++) {
buf[buf.length]=nodes[ii].nodeName+"<"+nodes[ii].id+">";
}
document.getElementById("result").innerHTML=buf.join(", ");
}
},
42
);
}
</script>
---