Textarea根据光标位置插入字符(IE,FF兼容)-简单的留言框

这两天帮朋友写个在线聊天的前端js代码,留言处需要根据光标的位置需要插入相应表情的代码,本来想来很简单的一点小功能却是让我做了两天晚上。

目标:1.当焦点在Textarea内部时需要根据光标的位置插入相应表情代码;2.当焦点不在Textarea内部时则需要把相应的表情代码附加给Textarea。

目标明确了接下来就开始考虑一下实现的办法了。首先考虑到的是能否确定光标在Textarea内部的位置,然后通过String.slice()或者String.subString()方法将内容拼在一起。看起来思路清晰明了,然后让我们开始实现。

FireFox实现比较简单,FF提供了Textaret.selectionStart和Textaret.selectionEnd这两个属性,根据名字我们就能看出来,我们可以很方便获取我们的光标的位置或者说是我们当前选中的内容的开始位置和结束位置。通过上面我们已经说过的思路我们实现了我们的目标。下面是简单的代码示例:

  1. //我们的Textarea对象,根据ID获取目标Textarea
  2. var tan=document.getElementById('message');
  3. //表情代码
  4. var faceCode=':)';
  5. //将表情插入到Textarea中
  6. tan.value=tan.value.subString(0,tan.selectionStart)+faceCode+tan.value.subString(tan.selectionEnd);

下一步我们来看IE下面该怎么处理,我发现IE下面没有提供类似于FireFox的相应属性,IE提供了一个全局的document.selection属性,根据DHTML手册是说这个属性能够作为用户的识别文档的那一部分正在被操作或者作为某一操作的结果返回给用户。同时它也提供了一个方法document.selection.createRange()的方法,可以从当前选中的内容中创建一个TextRange对象,用了操作当前被选中的内容。

当然同时Body,Textarea,Button,以及带Type文本的input也有一个createTextRange()的方法,但是却没有提供类似于FireFox下的相关属性或方法。

于是我就想通过这些已有的属性和方法来判断出来光标在当前Textarea中的位置。首先使用document.selection.createRange()创建一个当前选中的文本的TextRange,然后再创建一个Textarea的TextRange,这里值得我们注意的是:不能使用Textaret.createTextRange()这个方法创建Textarea的TextRange。是不是比较绕啊,这里因为后面要通过TextRange.compareEndPoints()这个方法比较两个TextRange两端的位置,要是使用了Textarea.createTextRange()方法创建在比较的时候会提示“无效的的参数”这个地方我也不是很清楚是为什么。所以我们要通过TextRange.duplicate()方法复制一个副本,然后通过TextRange.moveToElementText()方法定位到Textarea。是不是比较乱,下面是简单的示例代码:

  1. //我们的Textarea对象
  2. var tan=document.getElementById('message');
  3. //当前选中的TextRange
  4. range1=document.selection.createRange();
  5. //复制一个TextRange
  6. range2=range1.duplicate();
  7. //定位到Textarea
  8. range2.moveToElementText(tan);

这是用的主要方法,当然还有其他的一些TextRange.moveStart()等等诸如此类的方法,通过循环遍历不断的判断两个TextRange的端点,最后实现确定光标在Textarea内部的位置。这个在网上有相关的例子搜一下很多,不过貌似都是同一篇文章,呵呵:P在这里我就不再赘述了。

其实我们想一下,是不是我们进入误区了?我们开始要实现的是要在Textarea内部光标处插入一段文字,我们现在在做的反而是在拼命的确定光标的位置。

光标处,FireFox下面我们可以通过那两个属性来确定光标的位置,但是IE下面提供了一个全局的selection属性和TextRange这个对象,我们再去看一遍DHTML的手册,selection 对象的典型用途是作为用户的输入,以便识别正在对文档的哪一部分正在处理,或者作为某一操作的结果输出给用户。我们可以将操作输出给用户的!是不是有点豁然开朗了呢?

我们不需要确定Textarea中光标的位置,我们需要做的就是把当前Textarea内部选中的内容替换为我们要插入的文字就是!下面是示例代码:

  1. //使用selection对象创建当前选中内容的TextRange
  2. var sel = document.selection.createRange();
  3. //赋值
  4. sel.text = txt;
  5. //将光标移动到刚才添加的内容的后面
  6. sel.moveStart('character', -txt.length);
OK!就是这么简单,怎么样很简单的吧?我们需要做的就是在插入之前先检查一下,将焦点设置为Textarea。一下是完整的js代码:
  1. function AddText(faceBtn) {
  2. var txt=faceBtn.value;
  3. obj = document.getElementById('message');
  4. selection = document.selection;
  5. checkFocus();
  6. if(typeof(obj.selectionStart)!='undefined') {
  7. //document.getElementById('logs').innerHTML+=obj.selectionStart+' '+obj.selectionEnd;
  8. obj.value = obj.value.substr(0, obj.selectionStart) + txt + obj.value.substr(obj.selectionEnd);
  9. } else if(selection && selection.createRange) {
  10. var sel = selection.createRange();
  11. sel.text = txt;
  12. sel.moveStart('character', -txt.length);
  13. } else {
  14. obj.value += txt;
  15. }
  16. }
  17.  
  18. function checkFocus() {
  19. obj.focus();
  20. }

其实写到这我们要做的大部分功能就已经实现了,但是,在给Textarea获取焦点的时候FireFox和IE是不同的,FireFox获取焦点后光标是在所有文字的后面,而IE则是在前面,这个问题我想了好久也没想出什么好的方法来,如果您有什么好的解决方法还请告诉我一下,我的邮箱:xiaobaov2@gmail.com。
欢迎交流,共同进步:)

转载请注明原文出处《Textarea根据光标位置插入字符(IE,FF兼容)-简单的留言框》 如无特别声明,所有文章均遵守创作共用 署名-非商业-禁止演绎 3.0协议。

4条回复 发表于 “Textarea根据光标位置插入字符(IE,FF兼容)-简单的留言框”上

  1. Mover says:

    这个办法不错!

    [回复]

    DK 说:

    @Mover, 感谢支持~可惜还是有点小瑕疵。

    [回复]

  2. Mover says:

    继续努力。。。

    [回复]

  3. 别出心裁 says:

    hi,能交个朋友 友情链接吗。

    [回复]

我要评论