2010-05-31 21 views
5

我忘記了跨瀏覽器兼容性的那一刻,我只是想讓它工作。 我在做的是試圖修改一個腳本(你可能不需要知道這一點)位於typegreek.com基本腳本被發現here。基本上它是當你輸入字符時,它將你輸入的字符轉換成希臘字符並將它打印到屏幕上。我試圖做的是讓它在contentEditable div的工作(它只適用於Textareas)需要將光標位置設置爲contentEditable div的末尾,問題與選擇和範圍對象

我的問題是與這一個功能:用戶鍵入一個鍵,它得到的轉換爲希臘鍵,和進入一個函數,它通過一些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大於該範圍中定義的值,則用於添加新字符的函數會掛起。有任何想法嗎?

回答

14

在一個可勝任的div中執行跨瀏覽器比textarea更容易。以下假設你的contenteditable div有一個「希臘」的ID。

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; 
    } 
} 
+0

Bravo!它完美的工作! – DavidR 2010-05-31 17:42:40

+0

我有一個類似的例子,發現'range.collapse(false)'比'setStart' +'setEnd'更合適,但是您建議使用'sel.removeAllRanges'後跟'sel.addRange'證明_very_有用在WebKit瀏覽器上! +1 – 2014-05-15 15:39:53

+0

只是想說謝謝,經過努力使其工作2小時後發現這個 – 2016-09-01 09:54:58

0

我想你可能會設置超出偏移量的起始偏移量。

當您插入文本時,您應該在開始偏移量之前先設置結束偏移量。

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

當我嘗試這樣做時,它仍然無法解決問題。我正在考慮使用範圍可能不是這裏最好的解決方案。 – DavidR 2010-05-31 02:22:58

相關問題