Getting highlighted text + position in document

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • JE

    Getting highlighted text + position in document

    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;



    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
    joakimk@ii.uib. no
    Norway

    --
    joakim.knudsen@ nospam.spray.no

    Remove nospam to reply!
  • Yann-Erwan Perio

    #2
    Re: Getting highlighted text + position in document

    JE wrote:
    [color=blue]
    > 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.[/color]

    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="makeBo ld()">

    <script type="text/javascript">
    var makeBold = function() {

    function getSel() {
    if(window.getSe lection) return window.getSelec tion();
    else if(typeof document.select ion!="undefined ")
    return document.select ion;
    }

    function getSelectionRan ge() {
    var sel=getSel();
    if(sel) {
    if(sel.getRange At && sel.rangeCount) return sel.getRangeAt( 0);
    else if(sel.createRa nge) return sel.createRange ();
    }
    }

    function emptySelection( ){
    var sel=getSel();
    if(sel) {
    if(sel.empty) sel.empty();
    else if(sel.removeAl lRanges) sel.removeAllRa nges();
    }
    }

    function _makeBold(){
    var rng=getSelectio nRange();

    if(rng) {
    if(rng.execComm and) {
    rng.execCommand ("bold");
    } else if(rng.extractC ontents){
    var endc=rng.endCon tainer;
    var action=1; // make bold
    var b, src=rng.extract Contents();

    do {
    if(endc.nodeNam e.toLowerCase() =="b") {
    action=0; // unbold
    break;
    }
    } while((endc=end c.parentNode));

    if(action==1){
    b=document.crea teElement("b");
    b.appendChild(s rc);
    rng.insertNode( b);
    } else {
    rng.insertNode(
    function(nodeLi st, parent){
    parent=parent|| document.create DocumentFragmen t();
    for(var ii=0;ii<nodeLis t.length;ii++)
    parent.appendCh ild(
    arguments.calle e(
    nodeList[ii].childNodes,
    nodeList[ii].nodeName.toLow erCase()=="b" ?
    null : nodeList[ii--]
    )
    );
    return parent;
    }(src.childNode s)
    );
    }
    emptySelection( );
    }
    }
    return true;
    }

    function doNothing() {
    return false;
    }

    return typeof getSel()!="unde fined" ? _makeBold : doNothing;
    }();
    </script>

    ---


    HTH
    Yep.

    Comment

    • JE

      #3
      Re: Getting highlighted text + position in document

      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$293 82$626a14ce@new s.free.fr>, y-e.perio@em-lyon.com
      wrote:
      [color=blue]
      > JE wrote:
      >[color=green]
      > > 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.[/color]
      >
      > 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="makeBo ld()">
      >
      > <script type="text/javascript">
      > var makeBold = function() {
      >
      > function getSel() {
      > if(window.getSe lection) return window.getSelec tion();
      > else if(typeof document.select ion!="undefined ")
      > return document.select ion;
      > }
      >
      > function getSelectionRan ge() {
      > var sel=getSel();
      > if(sel) {
      > if(sel.getRange At && sel.rangeCount) return sel.getRangeAt( 0);
      > else if(sel.createRa nge) return sel.createRange ();
      > }
      > }
      >
      > function emptySelection( ){
      > var sel=getSel();
      > if(sel) {
      > if(sel.empty) sel.empty();
      > else if(sel.removeAl lRanges) sel.removeAllRa nges();
      > }
      > }
      >
      > function _makeBold(){
      > var rng=getSelectio nRange();
      >
      > if(rng) {
      > if(rng.execComm and) {
      > rng.execCommand ("bold");
      > } else if(rng.extractC ontents){
      > var endc=rng.endCon tainer;
      > var action=1; // make bold
      > var b, src=rng.extract Contents();
      >
      > do {
      > if(endc.nodeNam e.toLowerCase() =="b") {
      > action=0; // unbold
      > break;
      > }
      > } while((endc=end c.parentNode));
      >
      > if(action==1){
      > b=document.crea teElement("b");
      > b.appendChild(s rc);
      > rng.insertNode( b);
      > } else {
      > rng.insertNode(
      > function(nodeLi st, parent){
      > parent=parent|| document.create DocumentFragmen t();
      > for(var ii=0;ii<nodeLis t.length;ii++)
      > parent.appendCh ild(
      > arguments.calle e(
      > nodeList[ii].childNodes,
      > nodeList[ii].nodeName.toLow erCase()=="b" ?
      > null : nodeList[ii--]
      > )
      > );
      > return parent;
      > }(src.childNode s)
      > );
      > }
      > emptySelection( );
      > }
      > }
      > return true;
      > }
      >
      > function doNothing() {
      > return false;
      > }
      >
      > return typeof getSel()!="unde fined" ? _makeBold : doNothing;
      > }();
      > </script>
      >
      > ---
      >
      >
      > HTH
      > Yep.[/color]

      --
      joakim.knudsen@ nospam.spray.no

      Remove nospam to reply!

      Comment

      • Andrew Thompson

        #4
        Re: Getting highlighted text + position in document

        On Sun, 25 Jul 2004 23:38:41 +0200, JE wrote:
        [color=blue]
        > Plus I need to .... i.e. inserting <b></b>
        > tags...[/color]

        Why don't you try some *deleting* as well JE?
        <http://www.physci.org/kbd.jsp?key=del >

        That last post of yours came to 145 lines, 124
        of which did not need to be requoted..

        --
        Andrew Thompson
        http://www.PhySci.org/ Open-source software suite
        http://www.PhySci.org/codes/ Web & IT Help
        http://www.1point1C.org/ Science & Technology

        Comment

        • Yann-Erwan Perio

          #5
          Re: Getting highlighted text + position in document

          JE wrote:
          [color=blue]
          > 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...[/color]

          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="retur n saveChanges(thi s)">
          <input type="hidden" name="textModif ied" value="">
          <input type="submit" value="Save changes">
          </form>

          <script type="text/javascript">
          function saveChanges(frm ){
          if(document.get ElementById &&
          document.body &&
          document.body.c hildNodes &&
          typeof document.body.n odeValue!="unde fined") {

          var root=document.g etElementById(" text");
          var txt=[];
          var getHTML = function(node) {
          var buf=[];
          if(node.nodeTyp e==1){
          buf.push("<"+no de.nodeName+">" );
          for(var ii=0; ii<node.childNo des.length; ii++)
          buf.push(argume nts.callee(node .childNodes[ii]));
          buf.push("<\/"+node.nodeName +">");
          } else if(node.nodeTyp e==3){
          buf.push(node.n odeValue);
          }
          return buf.join("");
          }

          //frm.elements["textModifi ed"].value=root.inn erHTML;
          for(var j=0; j<root.childNod es.length; j++)
          txt.push(getHTM L(root.childNod es[j]));
          frm.elements["textModifi ed"].value=txt.join ("");
          return true;
          }
          return false;
          }
          </script>
          ---

          Comment

          Working...