资源描述
开发iframe富文本编辑器的一点体会.docx
《开发iframe富文本编辑器的一点体会.docx》由会员分享,可在线阅读,更多相关《开发iframe富文本编辑器的一点体会.docx(7页珍藏版)》请在冰点文库上搜索。
![开发iframe富文本编辑器的一点体会.docx](https://file1.bingdoc.com/fileroot1/2023-5/11/f8d9ce71-0ff4-4559-bcfa-19d585e40b8b/f8d9ce71-0ff4-4559-bcfa-19d585e40b8b1.gif)
开发iframe富文本编辑器的一点体会
Javascript开发iframe富文本编辑器的一点体会
前段时间有个需求是开发富文本编辑器,这个之前随做过,但看了需求,发现有些地方还需google就把遇到的问题记录一下。
写这篇文章时用的TinyMCE编辑器就很强大,但毕竟是第三方的,项目也考虑了这些,如果做些自定义的东西不太方便。
1.判断光标位置的元素(或者选中的部分)的样式。
光标位置改变的时候更新工具栏对应按钮的样式。
什么情况下光标的位置会改变呢?
是键盘方向键和鼠标点击,于是就判断键盘事件和鼠标事件来执行光标移动的处理。
a.获得光标位置或选中元素:
首先getSelection,创建range。
然后获得元素,获取到元素之后就可以或得样式、tagName等等,做更多的操作,运行代码:
复制代码代码如下:
DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN">
p{width:
600px;text-align:
left;text-indent:
2em;line-height:
20px;font-size:
12px}
textarea{width:
600px;height:
100px;font-size:
12px;overflow:
auto}
block;height:
150px;font-size:
12px;line-height:
150%">信息
functioncreateEditor(){
variframe=document.createElement('iframe');
iframe.id='iframe';
iframe.frameBorder=1;
iframe.width=400;
iframe.height=200;
document.body.appendChild(iframe);
returniframe;
}
varbind=function(element,eventType,fn,useCapture){
useCapture=useCapture||false;
if(arguments.length<3){
returntrue
};
if(window.addEventListener){
element.addEventListener(eventType,fn,useCapture);
}else{
element.attachEvent('on'+eventType,fn,useCapture);
}
}
//from司徒正美
varcss=document.defaultView?
function(el,style){
returndocument.defaultView.getComputedStyle(el,null).getPropertyValue(style)
}:
function(el,style){
style=style.replace(/\-(\w)/g,function($,$1){
return$1.toUpperCase();
});
returnel.currentStyle[style];
}
functionbindEditor(){
variframe=createEditor();
varifr_win=iframe.contentWindow;
varifr_doc=ifr_win.document;
vareditorContent='黑体;font-weight:
bold;">阿四大四大四大italic;text-decoration:
underline;">四大四大打算打打italic;color:
#ff0000;">双打萨斯大师';
ifr_doc.designMode='On';//可编辑
ifr_doc.contentEditable=true;
ifr_doc.open();
ifr_doc.writeln('
body{padding:
10px;margin:
0;font-size:
13px;font-family:
宋体;text-align:
left;overflow:
auto;word-wrap:
break-word;cursor:
text;background-color:
transparent;}body,p,font,div,ul,li{line-height:
1.5;}p,font,div,ul,li{line-height:
1.5;margin:
0;padding:
0}a{color:
#548DD4}
'+editorContent+'');
ifr_doc.close();
vargetRange=function(){
varrange=window.getSelection?
ifr_win.getSelection():
ifr_win.document.selection;
if(!
range){
return{
node:
null,
range:
null,
text:
null
};
}
range=range.createRange?
range.createRange():
range.getRangeAt(0);
vartext=window.getSelection?
range:
range.text;
varrangeNode=null;
if(monAncestorContainer){
rangeNode=monAncestorContainer;
}else{
if(range.parentElement)rangeNode=range.parentElement();
}
return{
node:
rangeNode,
range:
range,
text:
text
}
}
varinfo=document.getElementsByTagName('span')[0];
vargetStyle=function(node){
//console.log(node)
varhtml='';
html+=''+css(node,'font-family')+'">字体:
'+css(node,'font-family')+'
';
html+=''+css(node,'color')+'">颜色:
'+css(node,'color')+'
';
html+=''+css(node,'font-style')+'">斜体:
'+css(node,'font-style')+'
';
html+=''+css(node,'font-weight')+'">粗体:
'+css(node,'font-weight')+'
';
html+=''+css(node,'text-decoration')+'">下划线:
'+css(node,'text-decoration')+'
';
html+='tagName:
'+node.tagName+',style:
'+node.getAttribute('style')+'
';
info.innerHTML=html;
}
//当光标位置改变时候执行
varonselectionchange=function(event){
vare=event||window.event;
if(!
e.keyCode)e.keyCode=e.which;
//方向键移动光标,获取光标位置的dom
if((e.keyCode>=37&&e.keyCode<=40)||e.type=="click"){
varnode=getRange().node;//获取光标位置元素
if(node!
==null){
while(node.nodeType!
=1){
node=node.parentNode;
}
getStyle(node);
}
}
}
bind(ifr_doc,'click',onselectionchange,false);
bind(ifr_doc,'keydown',onselectionchange,false);
}
window.onload=function(){
bindEditor();
}
2.ie不能保持光标位置,这个是在添加超链接时候出现的问题,当不使用浏览器内置的输入框,光标移动其他的文本域里,ie会失去所选中的部分,无法对选中的部分加链接了,解决办法就是:
利用range的getBookmark和moveToBookmark,然后给iframe的document绑定onbeforedeactivate(getBookmark)、onactivate(moveTo),这2个事件的大致意思就是,当被激活和失去激活状态。
增加事件之后,就不必保存lastRang或者再其他地方设置bookmark了,可以让ie像其他浏览器一样自动保持光标位置了
复制代码代码如下:
if(Util.browser.msie){
Util.bind(this.E.ifr_win.document,"beforedeactivate",function(){
varRng=_self.getRange().range;
_self.rangeBookMark=Rng.getBookmark();
});
Util.bind(this.E.ifr_win.document,"activate",function(){
varRng=_self.getRange().range;
Rng.moveToBookmark(_self.rangeBookMark);
Rng.select();
_self.rangeBookMark=null;
});
}
3.ie中的撤销与重做。
当iframe外部有弹出窗口、或者修改html撤销、重做功能将失效。
只能归为ie的bug了。
。
。
。
也许ie没分清iframe和页面的document,把他们的撤销、重做混道义了。
如下:
复制代码代码如下:
DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN">
p{width:
600px;text-align:
left;text-indent:
2em;line-height:
20px;font-size:
12px}
textarea{width:
600px;height:
100px;font-size:
12px;overflow:
auto}
block;height:
150px;font-size:
12px;line-height:
150%">信息
functionchangeLayout(){
varpopwin=document.getElementById('popwin');
if(!
popwin){
popwin=document.createElement('div');
popwin.id='popwin';
popwin.style.cssText='display:
none;width:
300px;height:
150px;background-color:
#ccc;position:
absolute;left:
0;top:
0px;text-align:
center;line-height:
150px;';
popwin.innerHTML='改变了layoud渲染,ie将无法撤销、重做';
document.body.appendChild(popwin);
popwin.onclick=function(){this.style.display='none'};
}
popwin.style.display=popwin.style.display=='none'?
'block':
'none';
}
functioncreateEditor(){
variframe=document.createElement('iframe');
iframe.id='iframe';
iframe.frameBorder=1;
iframe.width=400;
iframe.height=200;
document.body.appendChild(iframe);
returniframe;
}
varbind=function(element,eventType,fn,useCapture){
useCapture=useCapture||false;
if(arguments.length<3){
returntrue
};
if(window.addEventListener){
element.addEventListener(eventType,fn,useCapture);
}else{
element.attachEvent('on'+eventType,fn,useCapture);
}
}
//from司徒正美
varcss=document.defaultView?
function(el,style){
returndocument.defaultView.getComputedStyle(el,null).getPropertyValue(style)
}:
function(el,style){
style=style.replace(/\-(\w)/g,function($,$1){
return$1.toUpperCase();
});
returnel.currentStyle[style];
}
functionbindEditor(){
variframe=createEditor();
varifr_win=iframe.contentWindow;
varifr_doc=ifr_win.document;
vareditorContent='黑体;font-weight:
bold;">阿四大四大四大italic;text-decoration:
underline;">四大四大打算打打italic;color:
#ff0000;">双打萨斯大师';
ifr_doc.designMode='On';//可编辑
ifr_doc.contentEditable=true;
ifr_doc.open();
ifr_doc.writeln('
body{padding:
10px;margin:
0;font-size:
13px;font-family:
宋体;text-align:
left;overflow:
auto;word-wrap:
break-word;cursor:
text;background-color:
transparent;}body,p,font,div,ul,li{line-height:
1.5;}p,font,div,ul,li{line-height:
1.5;margin:
0;padding:
0}a{color:
#548DD4}
'+editorContent+'');
ifr_doc.close();
vargetRange=function(){
varrange=window.getSelection?
ifr_win.getSelection():
ifr_win.document.selection;
if(!
range){
return{
node:
null,
range:
null,
text:
null
};
}
range=range.createRange?
range.createRange():
range.getRangeAt(0);
vartext=window.getSelection?
range:
range.text;
varrangeNode=null;
if(monAncestorContainer){
rangeNode=monAncestorContainer;
}else{
if(range.parentElement)rangeNode=range.parentElement();
}
return{
node:
rangeNode,
range:
range,
text:
text
}
}
varinfo=document.getElementsByTagName('span')[0];
vargetStyle=function(node){
//console.log(node)
varhtml='';
html+=''+css(node,'font-family')+'">字体:
'+css(node,'font-family')+'
';
html+=''+css(node,'color')+'">颜色:
'+css(node,'color')+'
';
html+=''+css(node,'font-style')+'">斜体:
'+css(node,'font-style')+'
';
html+=''+css(node,'font-weight')+'">粗体:
'+css(node,'font-weight')+'
';
html+=''+css(node,'text-decoration')+'">下划线:
'+css(node,'text-decoration')+'
';
html+='tagName:
'+node.tagName+',style:
'+node.getAttribute('style')+'
';
info.innerHTML=html;
}
//当光标位置改变时候执行
varonselectionchange=function(event){
vare=event||window.event;
if(!
e.keyCode)e.keyCode=e.which;
//方向键移动光标,获取光标位置的dom
if((e.keyCode>=37&&e.keyCode<=40)||e.type=="click"){
varnode