JE wrote:
My problem is that I also need the position of the selected text within
the document. I am finishing a Perl program for editing HTML content, and
I'd like to use such a script to submit words/paragraphs back to the
program, requesting HTML formatting tags. E.g. user selects "very
important", clicks the BOLD button. Then JS gets the text and its
position which is submitted to the Perl program, which adds <B></B> tags,
and refreshes the document.
This is not a simple problem; the position you're looking for in your
Perl program is a text-based one. However, you only have access to a
serialized source on the client, which means that the position defined
in regards of text isn't really an interesting one, and can vary across
user agents.
If it is acceptable to you to have the "bold" part be done client side
(and it should be since you rely on client objects to start the whole
process), then you could go for a client-side solution, using ranges -
submitting the serialized source to the Perl program afterwards, if
history is needed.
Ranges' models differ between IE and W3C models; IE's model is
text-oriented, offering a great deal of useful methods to directly
manipulate the text, while the W3C's one is more node-oriented, thus
requiring more code to achieve similar results (reorganizing, splitting
nodes etc).
---
<pre style="text-align:center">
Trois allumettes une à une allumées dans la nuit
La première pour voir ton visage tout entier
La seconde pour voir tes yeux
La dernière pour voir ta bouche
Et l'obscurité tout entière pour me rappeler tout cela
En te serrant dans mes bras
</pre>
<input type="button" value="Make Bold" onclick="makeBold()">
<script type="text/javascript">
var makeBold = function() {
function getSel() {
if(window.getSelection) return window.getSelection();
else if(typeof document.selection!="undefined")
return document.selection;
}
function getSelectionRange() {
var sel=getSel();
if(sel) {
if(sel.getRangeAt && sel.rangeCount) return sel.getRangeAt(0);
else if(sel.createRange) return sel.createRange();
}
}
function emptySelection(){
var sel=getSel();
if(sel) {
if(sel.empty) sel.empty();
else if(sel.removeAllRanges) sel.removeAllRanges();
}
}
function _makeBold(){
var rng=getSelectionRange();
if(rng) {
if(rng.execCommand) {
rng.execCommand("bold");
} else if(rng.extractContents){
var endc=rng.endContainer;
var action=1; // make bold
var b, src=rng.extractContents();
do {
if(endc.nodeName.toLowerCase()=="b") {
action=0; // unbold
break;
}
} while((endc=endc.parentNode));
if(action==1){
b=document.createElement("b");
b.appendChild(src);
rng.insertNode(b);
} else {
rng.insertNode(
function(nodeList, parent){
parent=parent||document.createDocumentFragment();
for(var ii=0;ii<nodeList.length;ii++)
parent.appendChild(
arguments.callee(
nodeList[ii].childNodes,
nodeList[ii].nodeName.toLowerCase()=="b" ?
null : nodeList[ii--]
)
);
return parent;
}(src.childNodes)
);
}
emptySelection();
}
}
return true;
}
function doNothing() {
return false;
}
return typeof getSel()!="undefined" ? _makeBold : doNothing;
}();
</script>
---
HTH
Yep.