2

I've got the following code to find a piece of text in IE11

var search_position = 0;
function findMyText(find)
{       
    // create range (selects all text)
    var range = document.body.createTextRange();
    range.moveToElementText(document.getElementById("editor"));

    if(search_position == 0)
    {
        range.moveStart("word", 0);                     
        range.findText(find);
    }

    // find the nth word that matches, where n is search_position
    for (var i = 0; i < search_position; i++)
    {
        range.moveStart("word", 1);                     
        range.findText(find);
    }

    search_position++;

    range.select();

    var l = range.text.length
    if(l < find.length)
    {
        search_position = 0;
    }
}

This finds each successive instance of find and selects it. It works by finding the first instance of a piece of text, marking the search index and then moving to the next word.

What I really want to do is start from a certain cursor position without looping through all the text. As in, if the user places the cursor in the middle of the text, I want to search from that point on. I also want to add a replace function. I can move to a specific character position like this

range.moveStart("character", x);

Where x is the character position. I can fetch this character position from the cursor position using the following code.

function getCaretPosition() {
    var ie = (typeof document.selection != "undefined" && document.selection.type != "Control") && true;
    var w3 = (typeof window.getSelection != "undefined") && true;
    var caretOffset = 0;
    if (w3) {
        var range = window.getSelection().getRangeAt(0);
        var preCaretRange = range.cloneRange();
        preCaretRange.selectNodeContents(editor);
        preCaretRange.setEnd(range.endContainer, range.endOffset);
        caretOffset = preCaretRange.toString().length;
    }
    else if (ie) {
        var textRange = document.selection.createRange();
        var preCaretTextRange = document.body.createTextRange();
        preCaretTextRange.expand(editor);
        preCaretTextRange.setEndPoint("EndToEnd", textRange);
        caretOffset = preCaretTextRange.text.length;
    }
    return caretOffset;
}

What I can't do, and need to, is find the current start position of my range. I need to know this for my replace method to work correctly. When I replace a word, I need to know where I am in the document.

range.startOffset returns undefined. So how do I get the position?

roryok
  • 9,325
  • 17
  • 71
  • 138
  • Would string.indexOf(find) be better for finding string positions? – garryp Apr 23 '15 at 19:37
  • If you have a range object (https://msdn.microsoft.com/en-us/library/ie/hh772133(v=vs.85).aspx), you may find the startOffset property (https://msdn.microsoft.com/en-us/library/ie/ff974930(v=vs.85).aspx) helpful. – Lance Leonard Apr 23 '15 at 22:17
  • @garryp I should have explained, the selection is htm0 (in a contenteditable div) so I can't use index of. – roryok Apr 24 '15 at 06:57
  • @LanceLeonard I did state that `range.startOffset` returns null here, it's at the end of the question – roryok Apr 24 '15 at 06:58
  • @garryp that should say html of course. I don't know how a 0 got in there!.... – roryok Apr 24 '15 at 07:34
  • I don't think startOffset is supported in IE – garryp Apr 24 '15 at 07:53
  • @garryp see this link - https://msdn.microsoft.com/en-us/library/ie/ff974930(v=vs.85).aspx – roryok Apr 24 '15 at 08:29
  • When I ran range.StartOffset on that code in IE it returns undefined – garryp Apr 24 '15 at 08:42
  • @garryp typo on my part, I meant to say it returns undefined not null. I've now changed that. – roryok Apr 24 '15 at 10:04
  • I think I might have a handle on this via a workaround, but it's not what I was hoping for. I can record cursor position on click as `x`, then skip that many chars using `range.moveStart("character",x)`, THEN start finding. As I move through the doc I can keep a character counter in a variable. This will also work for my replace function. I haven't tested this yet but if it works I'll post it as the answer – roryok Apr 27 '15 at 11:08

1 Answers1

0

I found a workaround by using Tim Down's excellent Rangy library. The following piece of code

var range = rangy.createRange();
range.setStart(document.getElementById("editor"), 0);

My find function ended up abandoning this approach, but this is how to solve the original problem using Rangy

roryok
  • 9,325
  • 17
  • 71
  • 138