最近在项目中碰到一个比较棘手的问题:

  在iframe富文本编辑器中,有个工具栏,这个工具栏在iframe标签之外,工具栏上有一个按钮,点击该按钮向iframe正在编辑中的光标处插入一个图片,图片会插入到当前光标所在的位置。但由于需求的需要,点击该按钮后需要弹出一个详细选项浮动层,选择详细的类型后再插入,如此,问题来了,当我点击了该按钮,浮动层显示出来后,iframe已经失去焦点,并不知道之前正在编辑的位置,所以编辑器默认把图片插入到编辑器内容的最前边(内部处理),编辑器及浮动层需求如下图:

解决尝试

一、利用模态弹出框

  首先声明这种方式是可行的,因为模态对话框会保持iframe编辑器的编辑状态,模态对话框的返回值可直接插入到之前正在编辑的光标位置,就像上面图中其他按钮一样,它们通过点击事件直接插入。但是对于上述需求,只是在该按钮位置添加了一个子类型选择列表框,用模态窗口显然得不到更好的人性化体验,这也不是我们所想要的。

  这时候如果能保存之前光标的编辑位置就好了,的确,在按钮的点击事件中,弹出浮动层的同时也保存好光标的位置,然后选择了详细类型后再将光标还原到原来的位置插入图片信息,经过尝试和摸索,令人欣喜的是,这种方式是可行的。

二、保存光标位置,选择后还原(1)

  这种方法主要通过document的selection对象来实现,在按钮的点击事件处理程序中,获取当前光标据文档开头的位置(即长度),然后保存,在选择了子类型后,根据之前保存的位置还原光标,然后插入图片信息,代码片段如下:

 //记录光标的位置,以备后续还原使用
var LastPos = 0;
//保存当前光标的位置
function SaveCusorPos() {
//获取编辑器焦点
var wobj = document.getElementById("myiframe").contentWindow;
wobj.focus();
if (document.selection) {
//ie,利用范围进行计算
var sText = wobj.document.selection.createRange();
//清除掉当前选中的内容
if (sText.htmlText != undefined && sText.htmlText != "") {
wobj.document.selection.clear();
}
//选择当前光标位置到文档开头之间的内容(以字符为单位)
sText.moveStart('character', -wobj.document.body.innerHTML.toString().length);
//计算选择内容的长度
LastPos = sText.text.length + FliterHtmlTag(sText.htmlText) + 1; //; //sText.htmlText.length; //
}
else if (wobj.selectionStart || wobj.selectionStart == "0") {
//firefox,直接读取编辑位置
LastPos = wobj.selectionStart;
}
}

上述代码不难理解,在ie中需要用范围计算当前光标位置距离文档开头的距离,而在firefox中,直接可以用编辑对象获取当前的编辑位置,下面是光标还原的代码:

 //把光标还原到之前保存的位置
function SetCusorPos() {
//获取编辑器对象焦点
var wobj = document.getElementById("myiframe").contentWindow;
wobj.focus();
if (wobj.document.body.setSelectionRange) {
//firefox,直接通过函数定位光标
wobj.document.body.setSelectionRange(LastPos, LastPos);
}
else if (wobj.document.selection.createRange()) {
//ie,用selection对象进行选择
var range = wobj.document.selection.createRange();
range.collapse(true);
//将选择区域的开始位置和结束位置都移动到之前保存的点
range.moveEnd('character', LastPos);
range.moveStart('character', LastPos);
//定位光标的位置
range.select();
}
}

在不同的浏览器中,处理方式均不一样,不过有一点是相通的,它们都是通过将选取的开始位置和结束位置重合来定位光标。

  经测试,这种方式是可行的,但它只能在纯文本处理的时候有用(IE中),问题在于这个保存点的计算,通过选区Text的length获取的长度是只是这个选区的文字长度,它并不能过滤多媒体元素(如图片、音视频等),这些元素在这个length中并没有包括,故存在多媒体元素的时候,这个光标保存点是不准的,会在实际位置的前面插入。此外,选区还有另外一个属性htmlText,获取它的长度又如何呢!?答案也是不行,这个长度包含了选区中html标签的所有字符,比如换行,段落等都被计算在内,这个光标保存点比实际的要大的多,会在实际位置的后面插入。

二、保存光标位置,选择后还原(2)

  上述两种方法都有自己的缺陷,经过摸索和查阅相关资料,在IE中有第三种方法可以实现此功能,就是selection对象的getBookmarkmoveToBookmark两个方法,前者获取一个对象,这个对象记录了当前编辑器中光标的位置信息,后者根据这个位置信息还原光标的位置。代码如下:

 //存储之前光标位置信息的对象
var ieSelectionBookMark = null;
//保存当前光标的位置
function SaveCusorPos() {
//编辑器获取焦点
var wobj = document.getElementById("myiframe").contentWindow;
wobj.focus();
if (document.selection) {
//获取当前光标的位置
var rangeObj = wobj.document.selection.createRange();
ieSelectionBookMark = rangeObj.getBookmark();
}
}
//把光标还原到之前保存的位置
function SetCusorPos() {
//编辑器获取焦点
var wobj = document.getElementById("myiframe").contentWindow;
wobj.focus();
if (ieSelectionBookMark) {
//还原光标的位置
var rangeObj = wobj.document.selection.createRange();
rangeObj.moveToBookmark(ieSelectionBookMark);
rangeObj.select();
ieSelectionBookMark = null;
}
}

上述代码改写了第二种方法中的两个函数,比较简洁,但这种方式在IE8中测试通过,其他不同版本浏览器中有待进一步验证,其他浏览器如firefox,利用第二种方式就可以实现。

如今浏览器五法八门,各自对标准的支持也不一样,导致了前端开发者做了大量的工作来弥补兼容性,不管怎样,相信会越来越好~~~

JavaScript Iframe富文本编辑器中的光标定位的更多相关文章

  1. php 解析富文本编辑器中的hmtl内容,富文本样式正确输出

    说明:富文本编辑器中的内容在直接获获取后需要解析以后才能在页面中正确显示 我在后端这样处理: $content = htmlspecialchars_decode($info['intro']); h ...

  2. 【JavaScript】富文本编辑器

    这是js写的富文本编辑器,还存在一些bug,但基本功能已经实现,通过这个练习,巩固了js富文本编辑方面的知识,里面包含颜色选择器.全屏.表情.上传图片等功能,每个功能实际对应的就是一个小插件啦 部分程 ...

  3. 过滤富文本编辑器中的html元素和其他元素

    https://blog.csdn.net/fjssharpsword/article/details/53467079 1.应用场景:从一份html文件中或从String(是html内容)中提取纯文 ...

  4. 对于富文本编辑器中使用lazyload图片懒加载

    使用lazyload.js图片懒加载的作用是给用户一个好的浏览体验,同时对服务器减轻了压力,当用户浏览到该图片的时候再对图片进行加载,项目中使用lazyload的时候需要将图片加入data-orgin ...

  5. 富文本编辑器直接从 word 中复制粘贴公式

    在之前在工作中遇到在富文本编辑器中粘贴图片不能展示的问题,于是各种网上扒拉,终于找到解决方案,在这里感谢一下知乎中众大神以及TheViper. 通过知乎提供的思路找到粘贴的原理,通过TheViper找 ...

  6. 对于MVC中应用百度富文本编辑器问题的解决办法

    1.对于应用富文本编辑器post提交表单内容提示有危险的解决办法: [ValidateInput(false)] //文本编辑器的表单提交不用提示危险 [HttpPost] public Action ...

  7. wangEditor-基于javascript和css开发的 Web富文本编辑器, 轻量、简洁、易用、开源免费(2)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. ssm项目中ueditor富文本编辑器的使用

    一.下载 https://ueditor.baidu.com/website/index.html 将ueditor放到项目中合适的位置 二 . 配置文件上传路径 在utf8-jsp/jsp/conf ...

  9. 富文本编辑器实现从word中复制图片(外挂)

    1问题 基于web的富文本编辑器的功能普遍较弱,而word是公认的宇宙第一好用的文档编辑器,所以许多人都习惯先在word中编辑,然后再将内容粘到web富文本编辑器中. 但是,这种操作有一个问题:图片带 ...

随机推荐

  1. hdoj 3665 Seaside【最短路】

    Seaside Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  2. UVA 10557 XYZZY

    Problem D: XYZZY ADVENT: /ad�vent/, n. The prototypical computer adventure game, first designed by W ...

  3. JMeter入门(1):JMeter总体介绍及组件介绍

    一.JMeter概述 JMeter就是一个测试工具,相比于LoadRunner等测试工具,此工具免费,且比较好用,但是前提当然是安装Java环境: JMeter可以做 (1)压力测试及性能测试: (2 ...

  4. hadoop错误org.apache.hadoop.mapred.TaskAttemptListenerImpl Progress of TaskAttempt

    错误: org.apache.hadoop.mapred.TaskAttemptListenerImpl: Progress of TaskAttempt 原因: 错误很明显,磁盘空间不足,但郁闷的是 ...

  5. 分布式服务框架 Zookeeper -- 管理分布式环境中的数据--转载

    原文:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/ Zookeeper 分布式服务框架是 Apache Hadoop ...

  6. android开发之PreferenceScreen使用详解

    是在惭愧,学习android也有一段时间了,今天才是第一次接触PreferenceScreen.记录下来,与大家分享. 本文参考:http://lovezhou.iteye.com/blog/1020 ...

  7. 前后端分离--mock

    fekit mock 数据 > fekit server -m mock.config 配置mock.config 支持正则 module.exports = { /queryProductDe ...

  8. vs2012 aspx 没有设计视图了?

    vs2012的html设计视图没有了!重新安装一次都不行!现在已经通过简单办法来解决了 其实当你打开 HTML设计器 设置时, “启用 HTML设计器"  这里是打勾的!这时千万不要放弃.先 ...

  9. ASP.NET MVC 第七回 UrlHelper

    这节讲 一下ASP.NET MVC中的Helper. 何谓Helper,其实就是在View中为了实现一些灵活功能而写的方法组. 其实ASP.NET MVC的View是Aspx的页面,本身可以声明定义方 ...

  10. Visual Studio小技巧

    换了台电脑后打开解决方案后所有项目都是展开状态,每天工作的第一件事情就是把他们都折起来,感觉好麻烦. 百度了一阵子没找到相关的问题,还一度怀疑是不是我自己的VS有问题. 但是其它解决方案没有这种情况, ...