Wang, Jay wrote:
I would like to enable some text between <SPAN
url="http://www.testserver.com/">WORD TO BE DRAGGED </SPAN>. I put some
javascript and it will extract http://www.testserver.com/ from the the span
element when I select the whole text in the SPAN and drag it.
This isn't an easy task, since you'd have to analyze text boundaries and
add/remove nodes in the tree. Ranges can help you, but they're supported
so far only by IE and Mozilla. You'll find an example below, not close
to satisfying, but which should nonetheless illustrate the use of many
range methods.
I've used an alternate click system instead of drag/drop, mostly because
of Mozilla not firing mouseup while dragging, and not offering ways to
prevent the drag (AFAIK).
I've also bumped into a strange bug as of Mozilla 1.7a, which would
require try/catch construct to be dealt with (adding an <input
type="text"> in the script, then clicking on it, fails miserably -
impossible to simply read a single property on the object).
<style type="text/css">
span[url]{background:yellow;}
</style>
<div>
Hello, <span url="foo.html">foo!</span>
You can drag and drop the foo where you want!
</div>
<script type="text/javascript">
window.onload=function(evt){
var d=document,rng;
if(d.body&&d.body.getAttribute&&d.body.nodeType&&
typeof d.body.parentNode!="undefined") {
if(d.body.createTextRange) rng=d.body.createTextRange();
else if(d.createRange) rng=d.createRange();
if(rng){
if(rng.moveToElementText&&rng.pasteHTML&&rng.moveT oPoint ||
rng.selectNode&&rng.insertNode&&rng.createContextu alFragment)
d.onclick=new Function("e","drag(e)");
}
}
}
var drag=(function(){
var dragEl;
function CRng(){
var d=document,rng;
if(d.body.createTextRange) { rng=d.body.createTextRange(); }
else if(d.createRange) { rng=d.createRange(); }
return rng;
}
function MRng(rng, el){
if(rng && el){
if(rng.moveToElementText) { rng.moveToElementText(el); }
else if(rng.selectNode) { rng.selectNode(el); }
}
return rng;
}
function SRng(rng){
if(rng){
if(rng.select) rng.select();
else{
with(this.getSelection()){
removeAllRanges();
addRange(rng);
}
}
}
return rng;
}
function WRng(rng,s){
if(rng){
if(rng.pasteHTML)rng.pasteHTML(s);
else rng.insertNode(rng.createContextualFragment(s));
}
return rng;
}
function hasAscendantNode(node,nodeName){
nodeName=nodeName.toLowerCase();
while(node&&node.nodeName.toLowerCase()!=nodeName)
node=node.parentNode;
return !!node;
}
function gtext(el){
if(typeof el.innerText!="undefined") return el.innerText;
else return (function(elmt){
for(var ii=0,buf=[],c=elmt.childNodes;ii<c.length;ii++){
if(c[ii].nodeType==3)buf.push(c[ii].nodeValue);
else if(c[ii].nodeType==1)buf.push(arguments.callee(c[ii]));
}
return buf.join("");
})(el);
}
return function(evt){
var tgt,rng,s,el;
evt=evt||window.event;
if(dragEl){
rng=CRng();
s="<a href='"+dragEl.getAttribute("url")+"'>"+
gtext(dragEl)+
"<\/a>";
if(rng.moveToPoint&&document.elementFromPoint){
tgt=document.elementFromPoint(evt.clientX,evt.clie ntY);
if(!hasAscendantNode(tgt,"a")&&
!hasAscendantNode(tgt,"input")&&
!hasAscendantNode(tgt,"textarea")){
rng.moveToPoint(evt.clientX,evt.clientY);
WRng(rng,s);
}
}else{
var c=evt.rangeParent,o=evt.rangeOffset;
if(c.nodeType==3){
c.splitText(o);
if(!hasAscendantNode(c,"a")&&
!hasAscendantNode(c,"input")&&
!hasAscendantNode(c,"textarea")){
rng.selectNode(c);
SRng(rng).collapse(false);
WRng(rng,s);
this.getSelection().removeAllRanges();
}
}
}
dragEl=null;
}else{
tgt=evt.originalTarget||evt.srcElement;
while(tgt&&tgt.nodeType!=1)tgt=tgt.parentNode;
if(tgt&&tgt.getAttribute("url"))
SRng(MRng(CRng(), dragEl=tgt));
}
};
})();
</script>
HTH
Yep.