需要将光标位置设置为contentEditable div的末尾,与选择和范围对象一起发出问题

时间:2010-05-31 00:51:15

标签: javascript range getselection

我暂时忘记了跨浏览器的兼容性,我只想让它发挥作用。 我正在做的是尝试修改位于typegreek.com的脚本(您可能不需要知道这个)。找到基本脚本here。基本上它的作用是当你输入字符时,它会将你输入的字符转换成希腊字符并将其打印到屏幕上。我想要做的是让它在contentEditable div上工作(它只适用于Textareas)

我的问题在于这一个功能:用户键入一个键,它被转换为一个希腊键,然后转到一个函数,它通过一些if进行排序,最后它在哪里可以添加div支持。这是我到目前为止所拥有的,

myField是div,myValue是希腊字符。

//Get selection object...
var userSelection
 if (window.getSelection) {userSelection = window.getSelection();}
 else if (document.selection) {userSelection = document.selection.createRange();}

//Now get the cursor position information...
var startPos = userSelection.anchorOffset;
var endPos = userSelection.focusOffset;
var cursorPos = endPos;

//Needed later when reinserting the cursor...
var rangeObj = userSelection.getRangeAt(0) 
var container = rangeObj.startContainer

//Now take the content from pos 0 -> cursor, add in myValue, then insert everything after myValue to the end of the line.
myField.textContent = myField.textContent.substring(0, startPos) + myValue + myField.textContent.substring(endPos, myField.textContent.length);

//Now the issue is, this updates the string, and returns the cursor to the beginning of the div. 
//so that at the next keypress, the character is inserted into the beginning of the div.
//So we need to reinsert the cursor where it was.

//Re-evaluate the cursor position, taking into account the added character.
  var cursorPos = endPos + myValue.length;

  //Set the caracter position.
  rangeObj.setStart(container,cursorPos) 

现在,只要我输入的内容不超过原始文本的大小,这种方法就有效。假设我手中有30个字符。如果我键入超过30,它会添加字符31,但将光标放回30.我可以在pos.31键入字符32,然后在pos.32键入字符33,但如果我尝试将字符34放入,则添加字符,并将光标设置为32.问题是,如果cursorPos大于范围中定义的值,则添加新字符的功能会搞定。有什么想法吗?

2 个答案:

答案 0 :(得分:16)

在一个可信的div中比在textarea中更容易做这个跨浏览器。以下假设您的contenteditable div的id为“greek”。

var greekChars = {
    "a": "\u03b1"
    // Add character mappings here
};

function convertCharToGreek(charStr) {
    return greekChars[charStr] || "[Greek]";
}

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

            // 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);
    }
}

var div = document.getElementById("greek");

div.onkeypress = function(evt) {
    evt = evt || window.event;
    var charCode = (typeof evt.which == "undefined") ? evt.keyCode : evt.which;
    if (charCode) {
        var charStr = String.fromCharCode(charCode);
        var greek = convertCharToGreek(charStr);
        insertTextAtCursor(greek);
        return false;
    }
}

答案 1 :(得分:0)

我认为您可能将起始偏移设置为超出结束偏移量。

在插入文本时,应首先在开始偏移之前设置结束偏移。

rangeObj.setEnd(container, cursorPos);
rangeObj.setStart(container,cursorPos);