• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    javascript开发随笔3 开发iframe富文本编辑器的一点体会
    就把遇到的问题记录一下。写这篇文章时用的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 style="display:block;height:150px; font-size:12px;line-height:150%">信息/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 style="font-family: 黑体; font-weight: bold;">阿四大四大四/span>大span style="font-style: italic; text-decoration: underline;">四大四大打算/span>打打span style="font-style: italic; color: #ff0000;">双打萨斯/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 style="font-family:'+ css(node,'font-family') +'">字体:'+ css(node,'font-family') + '/span>br />';
    html+= 'span style="color:'+ css(node,'color') +'">颜色:'+ css(node,'color') + '/span>br />';
    html+= 'span style="font-style:'+ css(node,'font-style') +'">斜体:'+ css(node,'font-style') + '/span>br />';
    html+= 'span style="font-weight:'+ css(node,'font-weight') +'">粗体:'+ css(node,'font-weight') + '/span>br />';
    html+= 'span style="text-decoration:'+ 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 style="display:block;height:150px; font-size:12px;line-height:150%">信息/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" onclick="changeLayout()" 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 style="font-family: 黑体; font-weight: bold;">阿四大四大四/span>大span style="font-style: italic; text-decoration: underline;">四大四大打算/span>打打span style="font-style: italic; color: #ff0000;">双打萨斯/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 style="font-family:'+ css(node,'font-family') +'">字体:'+ css(node,'font-family') + '/span>br />';
    html+= 'span style="color:'+ css(node,'color') +'">颜色:'+ css(node,'color') + '/span>br />';
    html+= 'span style="font-style:'+ css(node,'font-style') +'">斜体:'+ css(node,'font-style') + '/span>br />';
    html+= 'span style="font-weight:'+ css(node,'font-weight') +'">粗体:'+ css(node,'font-weight') + '/span>br />';
    html+= 'span style="text-decoration:'+ 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模拟撤销与重做了。网络这方面的资源还是不少的,就不在此详细说明了
    您可能感兴趣的文章:
    • nodejs后台集成ueditor富文本编辑器的实例
    • Vue.js结合Ueditor富文本编辑器的实例代码
    • Javascript实现简单的富文本编辑器附演示
    • 学习js在线html(富文本,所见即所得)编辑器
    • 19款Javascript富文本网页编辑器
    • 不到200行 JavaScript 代码实现富文本编辑器的方法
    上一篇:KindEditor 4.x 在线编辑器常用方法小结
    下一篇:TinyMCE syntaxhl插入代码后换行的修改方法
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    javascript开发随笔3 开发iframe富文本编辑器的一点体会 javascript,开发,随笔,iframe,