5

今のところ、クロスブラウザーの互換性について忘れています。これが機能することを望んでいます。私がやっていることは、typegreek.comにあるスクリプトを変更しようとしていることです (おそらくこれを知る必要はありません) 。基本的なスクリプトはここにあります。基本的に、文字を入力すると、入力している文字がギリシャ文字に変換され、画面に出力されます。私がやろうとしているのは、それを contentEditable div で動作させることです (Textareas でのみ動作します)。

私の問題は、この 1 つの関数にあります。ユーザーがキーを入力すると、ギリシャ語のキーに変換され、関数に移動し、いくつかの 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) 

これは、元のテキストのサイズを超えて入力しない限り機能します。事前に div に 30 文字あったとします。30 を超えて入力すると、文字 31 が追加されますが、カーソルは 30 に戻ります。位置 31 に文字 32 を入力し、位置 32 に文字 33 を入力できますが、文字 34 を入力しようとすると、文字を追加し、カーソルを 32 に戻します。問題は、cursorPos が範囲内で定義されている値よりも大きい場合、新しい文字を追加する関数が失敗することです。何か案は?

4

2 に答える 2

17

このクロスブラウザは、textareaよりもcontenteditabledivで実行する方が簡単です。以下は、contenteditabledivの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;
    }
}
于 2010-05-31T11:39:09.960 に答える
0

おそらく、開始オフセットを終了オフセットを超えて設定していると思います。

テキストを挿入するときは、開始オフセットの前に最初に終了オフセットを設定する必要があります。

rangeObj.setEnd(container, cursorPos);
rangeObj.setStart(container,cursorPos);
于 2010-05-31T01:55:27.243 に答える