JavaScript Iframe富文本编辑器中的光标定位

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

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

解决尝试

一、利用模态弹出框

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

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

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

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

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

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

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

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

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

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

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

 1 //存储之前光标位置信息的对象
 2 var ieSelectionBookMark = null;
 3 //保存当前光标的位置
 4 function SaveCusorPos() {
 5     //编辑器获取焦点
 6     var wobj = document.getElementById("myiframe").contentWindow;
 7     wobj.focus();
 8     if (document.selection) {
 9         //获取当前光标的位置
10         var rangeObj = wobj.document.selection.createRange();
11         ieSelectionBookMark = rangeObj.getBookmark();
12     }
13 }
14 //把光标还原到之前保存的位置
15 function SetCusorPos() {
16     //编辑器获取焦点
17     var wobj = document.getElementById("myiframe").contentWindow;
18     wobj.focus();
19     if (ieSelectionBookMark) {
20         //还原光标的位置
21         var rangeObj = wobj.document.selection.createRange();
22         rangeObj.moveToBookmark(ieSelectionBookMark);
23         rangeObj.select();
24         ieSelectionBookMark = null;
25     }
26 }

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

 

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

转载于:https://www.cnblogs.com/freshfish/p/3432907.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/460697.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Javascript中call函数和apply函数的使用

Javascript 中call函数和apply的使用: Javascript中的call函数和apply函数是对执行上下文进行切换,是将一个函数从当前执行的上下文切换到另一个对象中执行,例如: sourceObj.method.call(destObj,params1,params2) 是将sourceObj中…

搭建wordpress开发环境

安装php PHP下载地址:http://windows.php.net/download/ 和MySQL一样,下载包是一个zip压缩包,只需解压缩即可。将它解压缩到 D:\WNMP\php-5.5.6-Win32-VC11-x64目录下: 配置php 将php.ini-production文件复制并重命名为php.ini,并…

业界重磅新书《UNIX/Linux网络日志分析与流量监控》首发

《UNIX/Linux网络日志分析与流量监控》出版社官网: http://www.cmpbook.com/stackroom.php?id39384 每本图书附赠51CTO学院的价值100元学习卡一张京东:http://item.jd.com/11582561.html机械工业出版社在线购书平台:http://www.golden-book.…

Git工具使用基础

Git 是一个分布式的版本控制工具,本篇文章从介绍Git开始,重点在于介绍Git的基本命令和使用技巧,让你尝试使用Git的同时,体验到原来一个版 本控制工具可以对开发产生如此之多的影响,文章分为两部分,第一部分…

.NET:如何让线程支持超时?

背景 本文是为了回复博客园一个兄弟的问题,主要回答两个问题: 如何让线程支持超时?如何让线程在执行结束后销毁?MS 现在不推荐使用低级别的 Thread 编程,而推荐使用 Task,另外我多数情况都是做企业应用&…

第1章 Express MongoDB 搭建多人博客

学习环境 Node.js : 0.10.22 Express : 3.4.4 MongoDB : 2.4.8 快速开始 安装 Express express 是 Node.js 上最流行的 Web 开发框架,正如他的名字一样,使用它我们可以快速的开发一个 Web 应用。我们用 express 来搭…

Windows Phone 8初学者开发—第7部分:本地化应用程序

Windows Phone 8初学者开发—第7部分:本地化应用程序 原文 Windows Phone 8初学者开发—第7部分:本地化应用程序 第7部分:本地化应用程序 原文地址: http://channel9.msdn.com/Series/Windows-Phone-8-Development-for-Absolute-Beginners/Pa…

ARM官方汇编指令

以下内容源于网络资源的学习与整理,如有侵权请告知删除。 参考内容 (1)文档《ARM汇编指令集汇总》 (2)文档《ARM汇编手册》 (3)文档《ARM Software Development Toolkit User Guide》 内容总结…

audio 标签简介

定义和用法 <audio> 标签定义声音&#xff0c;比如音乐或其他音频流。 实例 一段简单的 HTML 5 音频&#xff1a; <audio src"someaudio.wav"> 您的浏览器不支持 audio 标签。 </audio> 提示和注释 提示&#xff1a;可以在开始标签和结束标签之间放…

magento 瘦身数据库

2019独角兽企业重金招聘Python工程师标准>>> 2013/4/1更新 有两种方式&#xff0c;一种在后台设置自动清除log数据 System > Configuration > Advanced > System 打开 Log Cleaning 还有一种自然是直接清理数据库 truncate dataflow_batch_export; truncat…

大数据时代的移动即时通讯

随着大数据的到来&#xff0c;第三方开放API的服务商越来越多&#xff0c;数据的挖掘和展示也在不断的更新。首先值得广大手机用户骄傲的事情&#xff0c;在移动通讯方面有了长足的发展&#xff0c;比如说你正在工作的时候&#xff0c;接听电话和打开视频的速度都相同的话&…

领域驱动设计和实践(转:http://kb.cnblogs.com/page/112298/)

引言 软件系统面向对象的设计思想可谓历史悠久&#xff0c;20世纪70年代的Smalltalk可以说是面向对象语言的经典&#xff0c;直到今天我们依然将这门语言视为面向对象语言的基础。随着编程语言和技术的发展&#xff0c;各种语言特性层出不穷&#xff0c;面向对象是大部分语言的…

CPU架构的简介

以下内容源于网络资源的学习与整理&#xff0c;如有侵权请告知删除。 注意&#xff0c;这篇文章是很早前发布的&#xff0c;里面的数据与描述与当下可能不符&#xff0c;仅当常识认知用。 CPU发展至今存在着很多种架构&#xff0c;比如x86架构、ARM架构、MIPS架构、PowerPC架构…

网络套接字socket的简介

以下内容源于C语言中文网的学习与整理&#xff0c;非原创&#xff0c;如有侵权请告知删除。 总结 socket的中文翻译是“套接字”&#xff0c;它是计算机之间进行通信的一种约定或一种方式。 套接字的典型应用就是web服务器和浏览器。 在Unix/Linux中&#xff0c;网络连接也是一…

IP、MAC和端口号

以下内容源于C语言中文网资料的学习与整理&#xff0c;非原创&#xff0c;如有侵权请告知删除。 在茫茫的互联网海洋中&#xff0c;要找到一台计算机非常不容易&#xff0c;有三个要素必须具备&#xff0c;它们分别是 IP 地址、MAC 地址和端口号。 IP地址 IP地址是 Internet Pr…

UML概述

UML视频一直在看&#xff0c;但是总觉得没有什么思路&#xff0c;知识都是零散的、片面的。最后复习阶段老师重新理了一下思路&#xff0c;我才觉得有点清晰了。所以&#xff0c;又回头把UML概述部分总结了一下。 感慨一句&#xff1a;思维导图真的要勤画&#xff0c;画图也是在…

TCP/IP模型简介(OSI模型的简化版)

以下内容源于C语言中文网的学习与整理&#xff0c;如有侵权请告知删除。 一、TCP/IP模型 1、模型的概念 OSI 是 Open System Interconnection 的缩写&#xff0c;译为“开放式系统互联”。OSI 模型把网络通信的工作分为 7 层&#xff0c;从下到上分别是物理层、数据链路层、网络…

图解TCP数据的传输(建立连接、数据传输、断开连接)

以下内容源于C语言中文网的学习与整理&#xff0c;非原创&#xff0c;仅作学习之用&#xff0c;如有侵权请告知删除。 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的通信协议&#xff0c;数据在传…

自定义Button,复写里面的onKeyDown,不起作用

李刚的Android疯狂讲义真是“疯狂”&#xff0c;浪费了3天时间&#xff0c;到底是他的代码有问题&#xff0c;还是怎么的不得而知。 问题描述&#xff1a;他的书里面第3.3基于回调事件处理Propagation的例程。是为了演示基于回调事件传播的例程序&#xff0c;源代码如下&#x…

与socket网络编程有关的函数

以下内容源于网络资源的学习与整理&#xff0c;如有侵权请告知删除。 基于TCP通信的服务模式 服务端 socket函数&#xff0c;获取网络连接的文件描述符 bind函数&#xff0c;将服务器的端口、ip地址与socket函数创建的文件描述符绑定 listen函数&#xff0c;监听服务器的当前端…