要获取 TextArea 中光标所选择的范围及其内容,对于大部分浏览器来说非常简单:只需要读取 selectionStart 和 selectionEnd 属性就完成了。但是 IE6 - IE8 的 textarea 元素没有这两个属性,所以我们需要改用 IE 中独有的 TextRange 对象。例子如下:
function getSelection(area) { var selstart, selend, seltext; if (area.selectionStart) { selstart = area.selectionStart; selend = area.selectionEnd; seltext = area.value.substring(selstart, selend); } else { var range1 = document.selection.createRange(); if (range1.parentElement() != area) return; var range2 = range1.duplicate(); range2.moveToElementText(area); range2.setEndPoint('EndToEnd', range1); selstart = range2.text.length - range1.text.length; selend = selstart + range1.text.length; seltext = range1.text; } return { selstart: selstart, selend: selend, seltext: seltext }; }
其中 range1.parentElement() == area 的判断是必需的,否则在 moveToElementText 这行 IE 会报错:"参数无效"(Invalid argument)。在网上搜索得知,这是因为对 TextRange 的修改必需保证该对象是获得焦点的。因此,我们也可以通过area.focus() 来避免这个问题。
另外,如果尝试直接用下面方式直接创建 range2 然后调整它的结束位置,同样会出现“参数无效”的错误:
...... var range2 = codearea.createTextRange(); range2.setEndPoint('EndToEnd', range1); ......
因此上面采用迂回的方法来创建 range2,IE 这个破玩意的问题多的是。
这种方法在旧版本 IE 中还有个问题:当光标在行首时,得到的 selstart 位置是上一行的行尾位置,比正确值小2(注意 IE 中的 textarea 换行是两个字符 \r\n)。具体的解决办法可以看参考资料。
参考资料:
[1] Finding selection start and end position in a textarea, in Internet Explorer
[2] How to get caret position in textarea?
[3] How to get the start and end points of selection in text area?
[4] IE's document.selection.createRange doesn't include leading or trailing blank lines
[5] Introduction to Range
[6] TextRange object - MSDN
[7] createTextRange method - MSDN
[8] moveToElementText method - MSDN
[9] setEndPoint method - MSDN
[A] parentElement method - MSDN
[B] Textarea根据光标位置插入字符(IE,FF兼容)
[C] TextRange对象的setEndPoint方法和compareEndPoints方法