浏览 495 次
|
精华帖 (0) :: 良好帖 (7) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
|---|---|
| 作者 | 正文 |
|
时间:2008-07-15 关键字: iframe换行问题
最近由于公司要开发一套OA系统,OA系统中有一个在线交流聊天的功能.本来想直接用textarea进行实现.不过由于不支持图片,不支持表情.用起来体验太差.于是选用可编辑的iframe进行实现.
但以前本人从没接触过这方面的东东,本来以为弄个可编辑的iframe,再弄几个插入图片,插入表情等等东西就可以了,不过一开始就遇到问题了.在iframe中单击换行的时候,iframe中会自动的将当前行包含在一个<p>标签中.可众所周知,<p>标签中,换行的行距那也忒大了.看着就不舒服.有什么好的解决办法呢? 开始时,我想的是截取键盘的点击事件,让按Enter键时的点击失效.然后在当前光标处添加一个<br />标签.可这个<br />要怎么插入呢.突然想起以前看到过的一个方法 document.execCommand("paste");这个方法就可以在光标所在处,插入剪帖版中的内容.近而联想到window对象中的clipboardData对象.不是可以直接设置剪贴版中的内容的方法么:window.clipboardData.setData("Text","value");于是有了本人的第一个解决方案:
<script>
window.onload=function(){
MyEditor.document.designMode="on";
MyEditor.document.onkeypress=function(){return keyPress(MyEditor.event);};
}
function keyPress(ev){
if(ev.keyCode==13){
//将剪贴版中的文本内容设置成为换行符\n.(在可编辑状态下\n代表的就是<br />);
window.clipboardData.setData("Text","\n");
//执行粘贴操作.
document.execCommand("paste");
//使点击Enter按钮失效.
return false;
}
return true;
}
</script>
<iframe id="MyEditor" name="MyEditor" style="width:400;height:400;font-size:12px;" frameborder=0 src="">
</iframe>
可这样一来.换行是成功了,可我剪贴版中的内容怎么办呢?于是我又想到了clipboardData对象的getData();方法于是我在将剪贴版内容替换为\n之前.将里面的内容给提取出来. var oldData=window.clipboardData.getData("Text");在执行粘贴操作后,再将它的值给设置回去.window.clipboardData.setData("Text",oldData);可每次执行它都会报错:OpenClipBoard失败.到MSDN上一看,才知道如果连续执行两次setData()操作.会出现一些无法控制的错误...
这让我想起了曾经的一个IE特性,在新创建一个input标签之后,无法直接让它获取焦点.和这个问题有那么一点点相似性. 在这里,我再一次认识到了延迟时间为0秒的setTimeout的威力:
if(ev.keyCode==13){
//将内容提取出来
var oldData=window.clipboardData.getData("Text");
//将剪贴版中的文本内容设置成为换行符\n.
window.clipboardData.setData("Text","\n");
//执行粘贴操作.
document.execCommand("paste");
//加上setTimeout之后,设置前贴版内容成功了.- -!无语...
setTimeout(function(){
window.clipboardData.setData("Text",oldData);
},"0");
//使点击Enter按钮失效.
return false;
}
OK,没错,可以正确执行了.IE没问题了.火狐呢?一试,郁闷了.window.clipboardData对象在FF中不支持,execCommand方法在FF中不支持.哎..写了半天,白写了.又要重头开始了,那有没有别的什么解决办法呢? 于是本人发挥了Baidu+Google神功,不是有一句话么,叫知之为知之,不知则百度(Google)知.可百度(Google)也不是万能的.搜了半天.全是同样的解决方案.而且还是个有BUG的解决方案,没有一个是真正可以直接拿来使用的.真不知道,这种解决方案怎么在网上流传得这么广,难道真是IT界没人才了?顺便在这里BS一下那些见到什么内容就抄的网站.麻烦转文章时看一下这样的文章值不值得转载,OK? 不过搜到的内容还是给了我一些小提示,让我发现了一些以前没有用到过的方法和属性: 1>document.selection,获取文档中的选中部分,如果没有,则得到的是光标所在的地点. 2>createRange(),document.selection的一个方法,用于将选中处设置为一个区域,然后对区域中的内容进行操作. 于是又写了一个解决方案: if(ev.keyCode==13){
//将选中区域的内容设置为\n,即<br />标签.
BenEditor.document.selection.createRange().text="\n";
//让事件失效
return false;
}
按理说应该是可以实现换行了,可iframe偏偏跟我作对,插入了一个\n之后.由于光标还是处于createRange()所形成的区域中.实际换行已经成功,<br />标签也已经生成了.但光标却没有换行.只是往后空出了一小块地方.我猜想,这一块空间,应该就是\n这个字符所形成的吧.那当我执行完成之后,把光标向后移一位,这样,不就实现了文档中换行,光标也接着换行吗? 在Google和DHTML文档的帮助下.终于完成了最后的解决方案:
<script>
window.onload=function(){
MyEditor.document.designMode="on";
MyEditor.document.onkeypress=function(){return keyPress(MyEditor.event);};
}
function keyPress(ev){
if(ev.keyCode==13){
//在光标所在处创建一个区域.
var range=BenEditor.document.selection.createRange();
//将区域的内容设置成为换行符.
range.text="\n";
//将区域的起始点向右移动一个字符的长度.
range.moveStart("character", 1);
//将光标移动到区域的结尾.(若为false则是移动到起始位置).
range.collapse(true);
//由于上面的一系列操作,使得区域的位置处在了\n之后,所以再次选择时,光标就到了新一行的结尾.完成换行.
range.select();
//使事件失效
return false;
}
return true;
}
</script>
<iframe id="MyEditor" name="MyEditor" style="width:400;height:400;font-size:12px;" frameborder=0 src="">
</iframe>
到IE下测试,没问题,再跑到FF底下运行,同样没错!绕了几个弯之后,在iframe中换行的问题终于得到了成功的解决. ----------------------------------------------------------------------------------------------- 这个问题可能并不常见,也没多少人会遇到. 但我发这个帖子是想把自己发现问题和找问题的过程写出来,跟大家一起分享.共同成长. 如果写的有问题,也欢迎指出. ----------------------------------------------------------------------------------------------- 后话: 绕了半天弯.才发现,原来解决换行问题不用这么麻烦的. 直接在iframe中,把p的css属性改一下.使用: p
{
margin:0px;
padding:0px;
}就可以实现了.
强烈的BS自己...并感谢Quake Wang的提示. 不过多走了这么多弯路也是有好处的,至少让我学到了很多以前没有接触到的属性. 每次找到一个错误,并解决的过程.就是一个学习的过程.这样会让你更深入的理解当前使用的技术. 不怕弯路多,就怕一帆风顺.一直没有弯路绕. 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
时间:2008-07-16
试试看设置p的line height css来解决你最早说的问题
|
|
| 返回顶楼 | |
|
时间:2008-07-16
Quake Wang 写道 试试看设置p的line height css来解决你最早说的问题
试了一下您所说的方法.确实实现了将换行的高度变矮了. 可不知为什么.第一次在iframe中按回车的时候.之前所写的内容会自动的向上飘浮一段距离. 不知道该怎么控制. |
|
| 返回顶楼 | |
|
时间:2008-07-16
我前面忘记说了margin也要处理,这个问题在做richeditor时候都会遇到,通常是给iframe设置p的css style来解决,比如
p { margin:0pt; line-height: ...; } |
|
| 返回顶楼 | |
|
时间:2008-07-16
Quake Wang 写道 我前面忘记说了margin也要处理,这个问题在做richeditor时候都会遇到,通常是给iframe设置p的css style来解决,比如 p { margin:0pt; line-height: ...; } ...这下更惨. 直接使用margin:0pt; 不是向上飘. 而是许多行完全重叠在一起了... 设置margin-top:0pt;和之前效果一样.还是向上飘. 设置padding也一样. |
|
| 返回顶楼 | |
|
时间:2008-07-16
shift+enter不行吗?
|
|
| 返回顶楼 | |
|
时间:2008-07-16
你还是给一个具体的例子吧,JavaEye的richeditor就是这样设置的,你可以在自己的博客界面用可视化编辑器发篇草稿试试看,用firebug查看一下样式表。
|
|
| 返回顶楼 | |
|
时间:2008-07-16
achun 写道 shift+enter不行吗?
shift+enter确实是可以实现的. 不过一般聊天或写文章.有谁会无聊到+shift来进行换行? |
|
| 返回顶楼 | |
|
时间:2008-07-16
...
我晕了.白跑了那么多弯跑. 原来换行问题只要用 p{ margin:0px; padding:0px; } 就可以成功解决了. 强烈的BS自己. 发这个帖子简直就是误人子弟. 顺便感谢Quake Wang的提示. |
|
| 返回顶楼 | |








