| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 | /** * 源码编辑插件 * @file * @since 1.2.6.1 */(function (){    var sourceEditors = {        textarea: function (editor, holder){            var textarea = holder.ownerDocument.createElement('textarea');            textarea.style.cssText = 'position:absolute;resize:none;width:100%;height:100%;border:0;padding:0;margin:0;overflow-y:auto;';            // todo: IE下只有onresize属性可用... 很纠结            if (browser.ie && browser.version < 8) {                textarea.style.width = holder.offsetWidth + 'px';                textarea.style.height = holder.offsetHeight + 'px';                holder.onresize = function (){                    textarea.style.width = holder.offsetWidth + 'px';                    textarea.style.height = holder.offsetHeight + 'px';                };            }            holder.appendChild(textarea);            return {                setContent: function (content){                    textarea.value = content;                },                getContent: function (){                    return textarea.value;                },                select: function (){                    var range;                    if (browser.ie) {                        range = textarea.createTextRange();                        range.collapse(true);                        range.select();                    } else {                        //todo: chrome下无法设置焦点                        textarea.setSelectionRange(0, 0);                        textarea.focus();                    }                },                dispose: function (){                    holder.removeChild(textarea);                    // todo                    holder.onresize = null;                    textarea = null;                    holder = null;                }            };        },        codemirror: function (editor, holder){            var codeEditor = window.CodeMirror(holder, {                mode: "text/html",                tabMode: "indent",                lineNumbers: true,                lineWrapping:true            });            var dom = codeEditor.getWrapperElement();            dom.style.cssText = 'position:absolute;left:0;top:0;width:100%;height:100%;font-family:consolas,"Courier new",monospace;font-size:13px;';            codeEditor.getScrollerElement().style.cssText = 'position:absolute;left:0;top:0;width:100%;height:100%;';            codeEditor.refresh();            return {                getCodeMirror:function(){                    return codeEditor;                },                setContent: function (content){                    codeEditor.setValue(content);                },                getContent: function (){                    return codeEditor.getValue();                },                select: function (){                    codeEditor.focus();                },                dispose: function (){                    holder.removeChild(dom);                    dom = null;                    codeEditor = null;                }            };        }    };    UE.plugins['source'] = function (){        var me = this;        var opt = this.options;        var sourceMode = false;        var sourceEditor;        var orgSetContent;        opt.sourceEditor = browser.ie  ? 'textarea' : (opt.sourceEditor || 'codemirror');        me.setOpt({            sourceEditorFirst:false        });        function createSourceEditor(holder){            return sourceEditors[opt.sourceEditor == 'codemirror' && window.CodeMirror ? 'codemirror' : 'textarea'](me, holder);        }        var bakCssText;        //解决在源码模式下getContent不能得到最新的内容问题        var oldGetContent,            bakAddress;        /**         * 切换源码模式和编辑模式         * @command source         * @method execCommand         * @param { String } cmd 命令字符串         * @example         * ```javascript         * editor.execCommand( 'source');         * ```         */        /**         * 查询当前编辑区域的状态是源码模式还是可视化模式         * @command source         * @method queryCommandState         * @param { String } cmd 命令字符串         * @return { int } 如果当前是源码编辑模式,返回1,否则返回0         * @example         * ```javascript         * editor.queryCommandState( 'source' );         * ```         */        me.commands['source'] = {            execCommand: function (){                sourceMode = !sourceMode;                if (sourceMode) {                    bakAddress = me.selection.getRange().createAddress(false,true);                    me.undoManger && me.undoManger.save(true);                    if(browser.gecko){                        me.body.contentEditable = false;                    }                    bakCssText = me.iframe.style.cssText;                    me.iframe.style.cssText += 'position:absolute;left:-32768px;top:-32768px;';                    me.fireEvent('beforegetcontent');                    var root = UE.htmlparser(me.body.innerHTML);                    me.filterOutputRule(root);                    root.traversal(function (node) {                        if (node.type == 'element') {                            switch (node.tagName) {                                case 'td':                                case 'th':                                case 'caption':                                if(node.children && node.children.length == 1){                                    if(node.firstChild().tagName == 'br' ){                                        node.removeChild(node.firstChild())                                    }                                };                                break;                                case 'pre':                                    node.innerText(node.innerText().replace(/ /g,' '))                            }                        }                    });                    me.fireEvent('aftergetcontent');                    var content = root.toHtml(true);                    sourceEditor = createSourceEditor(me.iframe.parentNode);                    sourceEditor.setContent(content);                    orgSetContent = me.setContent;                    me.setContent = function(html){                        //这里暂时不触发事件,防止报错                        var root = UE.htmlparser(html);                        me.filterInputRule(root);                        html = root.toHtml();                        sourceEditor.setContent(html);                    };                    setTimeout(function (){                        sourceEditor.select();                        me.addListener('fullscreenchanged', function(){                            try{                                sourceEditor.getCodeMirror().refresh()                            }catch(e){}                        });                    });                    //重置getContent,源码模式下取值也能是最新的数据                    oldGetContent = me.getContent;                    me.getContent = function (){                        return sourceEditor.getContent() || '<p>' + (browser.ie ? '' : '<br/>')+'</p>';                    };                } else {                    me.iframe.style.cssText = bakCssText;                    var cont = sourceEditor.getContent() || '<p>' + (browser.ie ? '' : '<br/>')+'</p>';                    //处理掉block节点前后的空格,有可能会误命中,暂时不考虑                    cont = cont.replace(new RegExp('[\\r\\t\\n ]*<\/?(\\w+)\\s*(?:[^>]*)>','g'), function(a,b){                        if(b && !dtd.$inlineWithA[b.toLowerCase()]){                            return a.replace(/(^[\n\r\t ]*)|([\n\r\t ]*$)/g,'');                        }                        return a.replace(/(^[\n\r\t]*)|([\n\r\t]*$)/g,'')                    });                    me.setContent = orgSetContent;                    me.setContent(cont);                    sourceEditor.dispose();                    sourceEditor = null;                    //还原getContent方法                    me.getContent = oldGetContent;                    var first = me.body.firstChild;                    //trace:1106 都删除空了,下边会报错,所以补充一个p占位                    if(!first){                        me.body.innerHTML = '<p>'+(browser.ie?'':'<br/>')+'</p>';                        first = me.body.firstChild;                    }                    //要在ifm为显示时ff才能取到selection,否则报错                    //这里不能比较位置了                    me.undoManger && me.undoManger.save(true);                    if(browser.gecko){                        var input = document.createElement('input');                        input.style.cssText = 'position:absolute;left:0;top:-32768px';                        document.body.appendChild(input);                        me.body.contentEditable = false;                        setTimeout(function(){                            domUtils.setViewportOffset(input, { left: -32768, top: 0 });                            input.focus();                            setTimeout(function(){                                me.body.contentEditable = true;                                me.selection.getRange().moveToAddress(bakAddress).select(true);                                domUtils.remove(input);                            });                        });                    }else{                        //ie下有可能报错,比如在代码顶头的情况                        try{                            me.selection.getRange().moveToAddress(bakAddress).select(true);                        }catch(e){}                    }                }                this.fireEvent('sourcemodechanged', sourceMode);            },            queryCommandState: function (){                return sourceMode|0;            },            notNeedUndo : 1        };        var oldQueryCommandState = me.queryCommandState;        me.queryCommandState = function (cmdName){            cmdName = cmdName.toLowerCase();            if (sourceMode) {                //源码模式下可以开启的命令                return cmdName in {                    'source' : 1,                    'fullscreen' : 1                } ? 1 : -1            }            return oldQueryCommandState.apply(this, arguments);        };        if(opt.sourceEditor == "codemirror"){            me.addListener("ready",function(){                utils.loadFile(document,{                    src : opt.codeMirrorJsUrl || opt.UEDITOR_HOME_URL + "third-party/codemirror/codemirror.js",                    tag : "script",                    type : "text/javascript",                    defer : "defer"                },function(){                    if(opt.sourceEditorFirst){                        setTimeout(function(){                            me.execCommand("source");                        },0);                    }                });                utils.loadFile(document,{                    tag : "link",                    rel : "stylesheet",                    type : "text/css",                    href : opt.codeMirrorCssUrl || opt.UEDITOR_HOME_URL + "third-party/codemirror/codemirror.css"                });            });        }    };})();
 |