selectionrangejavascripttextrange

Javascript: remember selected range of a text


I am trying to find a way to remember/store a JScript textrange and then apply it back to a text and convert it into a selection.

An example: in an iframe which is in "designmode" and contains the text "This is text inside the frame", the user hilights/selects "is text".

I can read that selection by using all the available range methods. No problem so far. Now clicking a button creates creates another iframe containing the same text as the first one and the first iframe gets removed. In that second iframe I want to select the same text the user selected in the first frame. Now the problems start: the range object from iframe 1 cannot be used for iframe 2. Somehow the range object seems to be tied to its source element. Setting the range has either no effect or weird errors. How can I re-select whatever WAS selected?


Solution

  • Yes, there is a way. textRange provides many methods/properties, for example to determine the position.

    So if you say, that's not a real copy, but identical, you can fetch the positions of frame1 and create upon them a new selection in frame2.

    I was playing around with it a little bit, here's the result:

    <html>
      <head>
      <title>title</title>
    
      <script type="text/jscript">
    
      function cloneSelection()
      {
        if(!document.all || window.opera)
        {
          alert('this is an jscript-example for MSIE5+');
          return;
        }
        var editors=window.frames;  
            editors[0].focus();
    
        //create 2 ranges in the first iframe 
        var r1=editors[0].document.selection.createRange();
        var r2=editors[0].document.selection.createRange();
    
        //checkout if a control is selected
        if(editors[0].document.selection.type==='Control')
        {    
          var obj=r1.item(0);
          var objs=editors[0].document.body.getElementsByTagName(obj.tagName);
    
          //iterate over the elements to get the index of the element
          for(var i=0;i<objs.length;++i)
          {
            if(objs[i]===obj)
            {
              //create a controlRange, add the found control and select it
              var controls=editors[1].document.body.createControlRange();
                  controls.add(editors[1].document.body.getElementsByTagName(obj.tagName)[i]);
                  controls.select()
              return;
            }
          }
          //control-branch done
        }
    
        //no control was selected, so we work with textRanges  
        //collapse the 2nd range created above 
        r2.collapse(false); 
    
        //store the positions of the 2 ranges
        var x1=r1.offsetLeft;
        var y1=r1.offsetTop;
        var x2=r2.offsetLeft;
        var y2=r2.offsetTop;
    
        //create ranges in the 2nd iframe and move them to the stored positions
        var r2=editors[1].document.body.createTextRange();
            r2.moveToPoint(x1,y1);
        var r3=editors[1].document.body.createTextRange();
            r3.moveToPoint(x2,y2);
    
        //set the move the end of the first range to start of the 2nd range
        r2.setEndPoint('EndToStart',r3);
    
        //select the first range
        r2.select(); 
      }
    
    
      //fill the iframes and make them editable
      window.onload=function()
      {
        var editors=window.frames;
        for(var i=0;i<frames.length;++i)
        {
          with(frames[i].document)
          {
            open();
            write('This is text is an image '+
                  '<br/><img src="http://sstatic.net/ads/img/careers-ad-header-so.png"><br/>'+
                  'this is inside this frame');
            designMode='On';
            close();
          }
        }
      }
      </script>
    
      <style type="text/css">
      <!--
      iframe{width:400px;height:200px;}
      -->
      </style>
      </head>
    
      <body>
        <center>
          <iframe src="about:blank"></iframe>
          <input type="button" value="cloneSelection()" onclick="cloneSelection()">
          <iframe src="about:blank"></iframe>
        </center>
      </body>
    </html>    
    

    test with jsFiddle

    Notice that this demo so far is build for MSIE only(you wrote you like to do it with JScript^^) .

    But it should also be possible to implement it for other browsers.