2

I found, somewhere in SE, a code to insert text in contenteditable by Tim Down. The code looks like the following and is working perfect. But I want to add a condition that is based on my requirement and wanted to modify the code somehow but failed to do it after so many trials.

function insertTextAtCursor(value, stepback) {
    var sel, range, textNode;
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);         
            textNode = document.createTextNode(value);


           //Check value of stepback: 0 or 1
            if(!stepback)//if 0
                 range.insertNode(textNode);
            if(stepback){ //if 1
               // replace the previously inserted character with the new one here

            }

            // Move caret to the end of the newly inserted text node   
            range.setStart(textNode, textNode.length);
            range.setEnd(textNode, textNode.length);

            sel.removeAllRanges();
            sel.addRange(range);          

        }
    } else if (document.selection && document.selection.createRange) {
        range = document.selection.createRange();
        range.pasteHTML(text);
    }
}

Here I am checking the value of the stepback parameter which is 0 or 1. If 0 then the pressed character will be inserted but if 1 I want to replace the last character with the new one. In my case, the stepback returns 1 when a key is pressed immediately followed by a vowel (for instance, pressing m followed by a). How can I modify the code to achieve this condition? Spent days to figure out this but to no avail.

Thanks.

Semytech
  • 623
  • 1
  • 10
  • 17
  • Could you please create a [fiddle](http://jsfiddle.net)? It's difficult to figure out what is it that you want from your code and its description. – Chandranshu Nov 15 '13 at 07:35
  • @Chandranshu I have other three or more functions that are associated with this function. My requirement is exactly like the one given in http://www.lexilogos.com/keyboard/amharic.htm. I have a set of mappings given in an array and based on the stepback the different values will be returned. I wish I could create a fiddle program but it is too much to put it there. You can press and see how the Ethiopian characters are getting replaced when you type any consonant followed by a vowel (a, e, i, u, o). – Semytech Nov 15 '13 at 08:06
  • Do you have the link to the original code on SE? I understand the functionality on the lexilogos.com site but I still don't understand what are you blocked on. Specifically, why is their code not good enough for you? – Chandranshu Nov 15 '13 at 08:26
  • The reason is that the editor in lexilogos.com is simple textarea. That code is working perfect with textarea. But I have modified it to work with contenteditable div where I have custom added some rich editing functionality. I took part of the code which inserts text in contenteditable from http://stackoverflow.com/questions/2940882/need-to-set-cursor-position-to-the-end-of-a-contenteditable-div-issue-with-sele. Every thing is fine except that on checking the value of the stepback I want to automatically replace the previous inserted textNode or character. – Semytech Nov 15 '13 at 08:34
  • Suddenly, everything is much clearer. I'm assuming that you have functions similar to the ones mentioned in that question. Someone should be able to answer it now. I'd recommend moving these links to the question itself while I think about it. – Chandranshu Nov 15 '13 at 08:39
  • 1
    @Chandranshu. How can I replace the character being returned from the one given in http://jsfiddle.net/MH5xX/ ? I think this may solve my issue. It returns the character right before the caret position and I want to replace it with another character on keypress – Semytech Nov 15 '13 at 08:54
  • Sorry, I didn't see your comment before posting the answer. Yes, you were very close to getting the answer. So, instead of extracting the last character, you just needed to delete it directly. The only problem I see with your approach is where you are setting the start of the range to be 0 which selects the whole text (which can be huge). Performance problems aside, this will not allow you to utilize the functions such as deleteContents(). – Chandranshu Nov 15 '13 at 09:19
  • 1
    http://stackoverflow.com/a/2943242/96100 – Tim Down Nov 15 '13 at 09:32

1 Answers1

4

In place of the following:

//Check value of stepback: 0 or 1
if(!stepback)//if 0
     range.insertNode(textNode);
if(stepback){ //if 1
   // replace the previously inserted character with the new one here

}

use the following code:

// This clones the selected range and then selects 1
// 1 character in the backward direction and deletes it.
if(stepback){
    clone = range.cloneRange();
    clone.setStart(range.startContainer, range.startOffset - 1);
    clone.setEnd(range.startContainer, range.startOffset);
    clone.deleteContents();
}
range.insertNode(textNode);

This ensures that the new translated character is always added at the end while optionally removing the 1 character in case stepback is required.

UPDATE: I have tested this in Chromium only.

Chandranshu
  • 3,669
  • 3
  • 20
  • 37
  • It works like a charm. Thank you very much Chandranshu. You know I almost spent days to figure out this. Long live SE. – Semytech Nov 15 '13 at 09:13
  • @semytech - Glad that this worked for you. You should accept the answer so that future users can use it as is w/o posting questions of their own. And if you think it's worthwhile, you can upvote it. It was a hard one to crack even after the problem became clear. – Chandranshu Nov 15 '13 at 09:21