Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Javascript > Getting highlighted text + position in document

Reply
Thread Tools

Getting highlighted text + position in document

 
 
JE
Guest
Posts: n/a
 
      07-24-2004
Hi!


I am snooping around all sorts of websites and faqs, in search of a way to
pick up any selected (mouse-highlighted) text in a HTML page, and store it
in a JavaScript variable.

I have found an excellent site which actually has a great cross-platform
script for doing just this;

http://www.quirksmode.org/js/selected.html

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.

Without the positions, I naturally get all occurrences of "very important"
in the document in boldface...

Please have a look at the two-liner script snippet in the Quirksmode
document. Is there any way to access position info without losing
cross-platform stability?


Your help would be greatly appreciated! I would love to see this idea
work.



Sincerely,

Joakim Knudsen
http://www.velocityreviews.com/forums/(E-Mail Removed)
Norway

--
(E-Mail Removed)

Remove nospam to reply!
 
Reply With Quote
 
 
 
 
Yann-Erwan Perio
Guest
Posts: n/a
 
      07-24-2004
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.
 
Reply With Quote
 
 
 
 
JE
Guest
Posts: n/a
 
      07-25-2004
Hi!

I looked at your solution, and it worked!
Still, I have trouble understanding your code, with all the DOM tree
manipulations. Plus I need to save the changes in style in a database, so
I would like to do the change at server-side; i.e. inserting <b></b>
tags...


- Joakim



In article <4102f3f9$0$29382$(E-Mail Removed)>, (E-Mail Removed)
wrote:

> 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.


--
(E-Mail Removed)

Remove nospam to reply!
 
Reply With Quote
 
Yann-Erwan Perio
Guest
Posts: n/a
 
      07-25-2004
JE wrote:

> Plus I need to save the changes in style in a database, so
> I would like to do the change at server-side; i.e. inserting <b></b>
> tags...


I can understand the feeling, however doing the change server-side would
be highly difficult, since the position has some sense on the client
only, in the DOM. You could of course do some text analysis on a
serialized DOM (say, obtained by innerHTML) also taking into account
nesting issues, or transmit a node/offset object then rebuild the
position server-side using a DOM parser, but as you can see this would
be a real pain to implement.

Actually, you don't need to do the change server-side to keep the
history; once the user has highlighted the text as required, he just has
to submit a form which will retrieve the source client-side (be it the
serialized source from innerHTML or, maybe better, a manually built
source from the DOM tree) and post it to the server.


Slightly tested only:

---
<pre id="text">
<b>He<i>ll</i>o</b>, World!
</pre>

<form action="foo" method="post" onsubmit="return saveChanges(this)">
<input type="hidden" name="textModified" value="">
<input type="submit" value="Save changes">
</form>

<script type="text/javascript">
function saveChanges(frm){
if(document.getElementById &&
document.body &&
document.body.childNodes &&
typeof document.body.nodeValue!="undefined") {

var root=document.getElementById("text");
var txt=[];
var getHTML = function(node) {
var buf=[];
if(node.nodeType==1){
buf.push("<"+node.nodeName+">");
for(var ii=0; ii<node.childNodes.length; ii++)
buf.push(arguments.callee(node.childNodes[ii]));
buf.push("<\/"+node.nodeName+">");
} else if(node.nodeType==3){
buf.push(node.nodeValue);
}
return buf.join("");
}

//frm.elements["textModified"].value=root.innerHTML;
for(var j=0; j<root.childNodes.length; j++)
txt.push(getHTML(root.childNodes[j]));
frm.elements["textModified"].value=txt.join("");
return true;
}
return false;
}
</script>
---
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How To? : Display text with highlighted background thricipio@gmail.com HTML 35 08-31-2008 03:48 AM
position image based on document position edouard.lauer@pt.lu Javascript 3 01-14-2006 06:04 PM
how to retrive highlighted text in a browser? wcc Python 3 07-04-2005 07:34 AM
Googlebar: can't read white text that's highlighted? GroupFug Firefox 4 03-28-2005 05:32 AM
Text editor with keywords highlighted MARTIN Herve \(EXT\) Java 2 11-03-2003 04:52 PM



Advertisments