javascript开发随笔3 开发iframe富文本编辑器的一点体会
javascript开发随笔3 开发iframe富文本编辑器的一点体会
发布时间:2016-12-29 来源:查字典编辑
摘要:就把遇到的问题记录一下。写这篇文章时用的TinyMCE编辑器就很强大,但毕竟是第三方的,项目也考虑了这些,如果做些自定义的东西不太方便。1....

就把遇到的问题记录一下。写这篇文章时用的TinyMCE编辑器就很强大,但毕竟是第三方的,项目也考虑了这些,如果做些自定义的东西不太方便。

1. 判断光标位置的元素(或者选中的部分)的样式。光标位置改变的时候更新工具栏对应按钮的样式。什么情况下光标的位置会改变呢?是键盘方向键和鼠标点击,于是就判断键盘事件和鼠标事件来执行光标移动的处理。

a. 获得光标位置或选中元素:首先getSelection,创建range。然后获得元素,获取到元素之后就可以或得样式、tagName等等,做更多的操作,运行代码:

复制代码 代码如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<title></title>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<style type="text/css">

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}

</style>

</head>

<body>

<span>信息</span>

<script type="text/javascript">

function createEditor(){

var iframe = document.createElement('iframe');

iframe.id = 'iframe';

iframe.frameBorder = 1;

iframe.width = 400;

iframe.height = 200;

document.body.appendChild(iframe);

return iframe;

}

var bind = function(element,eventType,fn,useCapture){

useCapture = useCapture || false;

if(arguments.length < 3){

return true

};

if(window.addEventListener){

element.addEventListener(eventType, fn, useCapture);

}else{

element.attachEvent('on'+eventType,fn, useCapture);

}

}

//from 司徒正美

var css = document.defaultView ? function(el,style){

return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)

} : function(el,style){

style = style.replace(/-(w)/g, function($, $1){

return $1.toUpperCase();

});

return el.currentStyle[style];

}

function bindEditor(){

var iframe = createEditor();

var ifr_win = iframe.contentWindow;

var ifr_doc = ifr_win.document;

var editorContent = '<span>阿四大四大四</span>大<span>四大四大打算</span>打打<span>双打萨斯</span>大师';

ifr_doc.designMode='On';//可编辑

ifr_doc.contentEditable = true;

ifr_doc.open();

ifr_doc.writeln('<html><head><style type="text/css">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}</style></head><body>'+ editorContent +'</body></html>');

ifr_doc.close();

var getRange = function(){

var range = 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);

var text = window.getSelection ? range : range.text;

var rangeNode = null;

if (range.commonAncestorContainer) {

rangeNode = range.commonAncestorContainer;

} else {

if (range.parentElement) rangeNode = range.parentElement();

}

return {

node : rangeNode,

range : range,

text : text

}

}

var info = document.getElementsByTagName('span')[0];

var getStyle = function(node){

//console.log(node)

var html = '';

html+= '<span+ css(node,'font-family') +'">字体:'+ css(node,'font-family') + '</span><br />';

html+= '<span+ css(node,'color') +'">颜色:'+ css(node,'color') + '</span><br />';

html+= '<span+ css(node,'font-style') +'">斜体:'+ css(node,'font-style') + '</span><br />';

html+= '<span+ css(node,'font-weight') +'">粗体:'+ css(node,'font-weight') + '</span><br />';

html+= '<span+ css(node,'text-decoration') +'">下划线:'+ css(node,'text-decoration') + '</span><br />';

html+= 'tagName:'+ node.tagName + ',style:'+ node.getAttribute('style') +'<br />';

info.innerHTML = html;

}

//当光标位置改变时候执行

var onselectionchange = function(event){

var e = event || window.event;

if(!e.keyCode)e.keyCode = e.which;

//方向键移动光标,获取光标位置的dom

if((e.keyCode >= 37 && e.keyCode <= 40 )|| e.type == "click"){

var node = 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();

}

</script>

</body>

</html>

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(){

var Rng = _self.getRange().range;

_self.rangeBookMark= Rng.getBookmark();

});

Util.bind(this.E.ifr_win.document, "activate", function(){

var Rng = _self.getRange().range;

Rng.moveToBookmark(_self.rangeBookMark);

Rng.select();

_self.rangeBookMark = null;

});

}

3. ie中的撤销与重做 。 当iframe外部有弹出窗口、或者修改html撤销、重做功能将失效。只能归为ie的bug了。。。。也许ie没分清iframe和页面的document,把他们的撤销、重做混道义了。

如下:

复制代码 代码如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<title></title>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<style type="text/css">

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}

</style>

</head>

<body>

<span>信息</span>

<div id="J_tool">

<input type="button" command="Undo" value="撤销" unselectable="on" />

<input type="button" command="Redo" value="重做" unselectable="on" />

<input type="button" command="Bold" value="粗体" unselectable="on" />

<input type="button" command="Italic" value="斜体" unselectable="on" />

</div>

<br />

<input type="button" value="点击下,ie将无法撤销、重做" />

<br />

<script type="text/javascript">

function changeLayout(){

var popwin = 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';

}

function createEditor(){

var iframe = document.createElement('iframe');

iframe.id = 'iframe';

iframe.frameBorder = 1;

iframe.width = 400;

iframe.height = 200;

document.body.appendChild(iframe);

return iframe;

}

var bind = function(element,eventType,fn,useCapture){

useCapture = useCapture || false;

if(arguments.length < 3){

return true

};

if(window.addEventListener){

element.addEventListener(eventType, fn, useCapture);

}else{

element.attachEvent('on'+eventType,fn, useCapture);

}

}

//from 司徒正美

var css = document.defaultView ? function(el,style){

return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)

} : function(el,style){

style = style.replace(/-(w)/g, function($, $1){

return $1.toUpperCase();

});

return el.currentStyle[style];

}

function bindEditor(){

var iframe = createEditor();

var ifr_win = iframe.contentWindow;

var ifr_doc = ifr_win.document;

var editorContent = '<span>阿四大四大四</span>大<span>四大四大打算</span>打打<span>双打萨斯</span>大师';

ifr_doc.designMode='On';//可编辑

ifr_doc.contentEditable = true;

ifr_doc.open();

ifr_doc.writeln('<html><head><style type="text/css">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}</style></head><body>'+ editorContent +'</body></html>');

ifr_doc.close();

var getRange = function(){

var range = 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);

var text = window.getSelection ? range : range.text;

var rangeNode = null;

if (range.commonAncestorContainer) {

rangeNode = range.commonAncestorContainer;

} else {

if (range.parentElement) rangeNode = range.parentElement();

}

return {

node : rangeNode,

range : range,

text : text

}

}

var info = document.getElementsByTagName('span')[0];

var getStyle = function(node){

//console.log(node)

var html = '';

html+= '<span+ css(node,'font-family') +'">字体:'+ css(node,'font-family') + '</span><br />';

html+= '<span+ css(node,'color') +'">颜色:'+ css(node,'color') + '</span><br />';

html+= '<span+ css(node,'font-style') +'">斜体:'+ css(node,'font-style') + '</span><br />';

html+= '<span+ css(node,'font-weight') +'">粗体:'+ css(node,'font-weight') + '</span><br />';

html+= '<span+ css(node,'text-decoration') +'">下划线:'+ css(node,'text-decoration') + '</span><br />';

html+= 'tagName:'+ node.tagName + ',style:'+ node.getAttribute('style') +'<br />';

info.innerHTML = html;

}

//当光标位置改变时候执行

var onselectionchange = function(event){

var e = event || window.event;

if(!e.keyCode)e.keyCode = e.which;

//方向键移动光标,获取光标位置的dom

if((e.keyCode >= 37 && e.keyCode <= 40 )|| e.type == "click"){

var node = 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);

bind(document.getElementById('J_tool'),'click',function(event){

event = event || window.event;

var target = event.srcElement || event.target;

var command = target.getAttribute('command');

var param = target.getAttribute('param') || '';

ifr_doc.execCommand(command,false,param);

return false;

})

}

window.onload = function(){

bindEditor();

}

</script>

</body>

</html>

如何解决呢? 只能依靠javascript模拟撤销与重做了。网络这方面的资源还是不少的,就不在此详细说明了

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新网页编辑器学习
热门网页编辑器学习
编程开发子分类