2008-10-24 46 views

回答

22

我会再次发布这个函数,看看这个问题是从另一个链接。

以下将在所有浏览器中完成这项工作,并处理所有新行问题而不会严重影响性能。我已经在some toing and froing之后到达此处,现在我相当确信这是最好的功能。

UPDATE

这个函数承担textarea的/输入具有焦点,所以你可能需要调用它之前调用的textarea的focus()方法。

function getInputSelection(el) { 
    var start = 0, end = 0, normalizedValue, range, 
     textInputRange, len, endRange; 

    if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") { 
     start = el.selectionStart; 
     end = el.selectionEnd; 
    } else { 
     range = document.selection.createRange(); 

     if (range && range.parentElement() == el) { 
      len = el.value.length; 
      normalizedValue = el.value.replace(/\r\n/g, "\n"); 

      // Create a working TextRange that lives only in the input 
      textInputRange = el.createTextRange(); 
      textInputRange.moveToBookmark(range.getBookmark()); 

      // Check if the start and end of the selection are at the very end 
      // of the input, since moveStart/moveEnd doesn't return what we want 
      // in those cases 
      endRange = el.createTextRange(); 
      endRange.collapse(false); 

      if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { 
       start = end = len; 
      } else { 
       start = -textInputRange.moveStart("character", -len); 
       start += normalizedValue.slice(0, start).split("\n").length - 1; 

       if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) { 
        end = len; 
       } else { 
        end = -textInputRange.moveEnd("character", -len); 
        end += normalizedValue.slice(0, end).split("\n").length - 1; 
       } 
      } 
     } 
    } 

    return { 
     start: start, 
     end: end 
    }; 
} 

var el = document.getElementById("your_input"); 
el.focus(); 
var sel = getInputSelection(el); 
alert(sel.start + ", " + sel.end); 
+2

我们是否可以根据某些非病毒许可证获得此许可,或者甚至可以为公有领域做出贡献? (这是那些关心版权的人的声音:-)) – 2010-12-10 22:37:06

6

我目前的解决方案是详细的,并基于this thread,但我打开更好的解决方案。

function getSelection(inputBox) { 
    if ("selectionStart" in inputBox) { 
     return { 
      start: inputBox.selectionStart, 
      end: inputBox.selectionEnd 
     } 
    } 

    //and now, the blinkered IE way 
    var bookmark = document.selection.createRange().getBookmark() 
    var selection = inputBox.createTextRange() 
    selection.moveToBookmark(bookmark) 

    var before = inputBox.createTextRange() 
    before.collapse(true) 
    before.setEndPoint("EndToStart", selection) 

    var beforeLength = before.text.length 
    var selLength = selection.text.length 

    return { 
     start: beforeLength, 
     end: beforeLength + selLength 
    } 
} 
+0

这与新生产线的问题。请参阅@ bobince的回答关于此的一些背景,以及我对解决方案的回答。 – 2010-11-17 18:25:56

7

IE的范围实现是一个slithy恐怖。它确实希望您使用可执行的execCommand接口,而不是涉及索引到文本中的任何内容。

我知道有两种获取索引的方法,它们都有问题。第一个使用range.text和你的示例代码一样。不幸的是,range.text有一个习惯,即删除前导和尾随的换行符,这意味着如果脱字符/选择位于第一行以外的行的起始位置,beforeLength将会被(换行符数* 2)字符和您会得到错误的选定文本。

第二种方法是使用range.moveStart/End(在重复范围内),如以下问题的答案中所述:Character offset in an Internet Explorer TextRange(但是,因为您正在使用已知的textarea父级,可以忽略关于node-发现)。这并没有相同的问题,但它报告所有的索引,就好像换行符是简单的LF字符,即使textarea.value和range.text将它们作为CRLF序列返回!所以你不能直接使用它们来索引textarea,但是你可以用一堆换行符来修复它们,或者只是用字符串替换掉所有的值,然后再使用它。

0

BootstrapFormHelpers

function getCursorPosition($element) { 
    var position = 0, 
     selection; 

    if (document.selection) { 
     // IE Support 
     $element.focus(); 
     selection = document.selection.createRange(); 
     selection.moveStart ('character', -$element.value.length); 
     position = selection.text.length; 
    } else if ($element.selectionStart || $element.selectionStart === 0) { 
     position = $element.selectionStart; 
    } 

    return position; 
    } 

    function setCursorPosition($element, position) { 
    var selection; 

    if (document.selection) { 
     // IE Support 
     $element.focus(); 
     selection = document.selection.createRange(); 
     selection.moveStart ('character', -$element.value.length); 
     selection.moveStart ('character', position); 
     selection.moveEnd ('character', 0); 
     selection.select(); 
    } else if ($element.selectionStart || $element.selectionStart === 0) { 
     $element.selectionStart = position; 
     $element.selectionEnd = position; 
     $element.focus(); 
    } 
    }