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

  在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. JS中多个onload冲突解决办法

    一  多个window.onload冲突 在一个页面中有两个JavaScript 分别都用到了window.onload一个是:window.onload=externallinks,另一个是:win ...

  2. JAVA虚拟机简介

    Java虚拟机定义 Java虚拟机有多层含义 一套规范:Java虚拟机规范.定义概念上Java虚拟机的行为表现 一种实现:例如HotSpot,J9,JRockit.需要实现JVM规范,但具体实现方式不 ...

  3. 上海Uber优步司机奖励政策(2月1日~2月7日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  4. 【转】Flask安装

    Flask 依赖两个外部库:Werkzeug 和 Jinja2 . Werkzeug 是一个 WSGI(在 Web 应用和多种服务器之间的标准 Python 接口) 工具集.Jinja2 负责渲染模板 ...

  5. zzuoj 10407: B.最大岛屿

    10407: B.最大岛屿 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 12  Solved: 5[Submit][Status][Web Board ...

  6. c#+ArcEngine中的IGroupLayer的用法

    转自羊子雄起原文c#+ArcEngine中的IGroupLayer的用法 在AE开发中,我们知道axMapControl.LayerCount能获取图层的数量,但是这种方法不能获取到图层组里面的图层, ...

  7. SSO之CAS备忘

    http://blog.chinaunix.net/uid-28380443-id-4740103.html 自己负责的公司基于CAS单点登录平台架构已经上线运行,很多细节的东西是时候备忘一下了,开源 ...

  8. 【转】YUV420P的格式以及转换为RGB565的代码(Android摄像头的输出一般为YUV420P)

    http://blog.csdn.net/daisyhd/article/details/38866809 static void cvt_420p_to_rgb565(int width, int  ...

  9. 仿path菜单button的实现

    path刚出来时.其菜单button也算是让大多数人感到了惊艳,如今看来事实上是非常easy的就是动画的结合. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQ ...

  10. android 5.0开发环境搭建

    Android 5.0 是 Google 于 2014 年 10 月 15 日发布的全新 Android 操作系统.本文将就最新的Android 5.0 开发环境搭建做详细介绍. 工具/原料 jdk- ...