///import core ///import plugins/serialize.js ///import plugins/undo.js ///commands 查看源码 ///commandsName Source ///commandsTitle 查看源码 (function (){ function SourceFormater(config){ config = config || {}; this.indentChar = config.indentChar || ' '; this.breakChar = config.breakChar || '\n'; this.selfClosingEnd = config.selfClosingEnd || ' />'; } var unhtml1 = function (){ var map = { '<': '<', '>': '>', '"': '"', "'": ''' }; function rep( m ){ return map[m]; } return function ( str ) { str = str + ''; return str ? str.replace( /[<>"']/g, rep ) : ''; }; }(); var inline = utils.extend({a:1,A:1},dtd.$inline,true); function printAttrs(attrs){ var buff = []; for (var k in attrs) { buff.push(k + '="' + unhtml1(attrs[k]) + '"'); } return buff.join(' '); } SourceFormater.prototype = { format: function (html){ var node = UE.serialize.parseHTML(html); this.buff = []; this.indents = ''; this.indenting = 1; this.visitNode(node); return this.buff.join(''); }, visitNode: function (node){ if (node.type == 'fragment') { this.visitChildren(node.children); } else if (node.type == 'element') { var selfClosing = dtd.$empty[node.tag]; this.visitTag(node.tag, node.attributes, selfClosing); this.visitChildren(node.children); if (!selfClosing) { this.visitEndTag(node.tag); } } else if (node.type == 'comment') { this.visitComment(node.data); } else { this.visitText(node.data,dtd.$notTransContent[node.parent.tag]); } }, visitChildren: function (children){ for (var i=0; i'); this.indents += this.indentChar; } if (!inline[tag]) { this.newline(); } }, indent: function (){ this.buff.push(this.indents); this.indenting = 0; }, newline: function (){ this.buff.push(this.breakChar); this.indenting = 1; }, visitEndTag: function (tag){ this.indents = this.indents.slice(0, -this.indentChar.length); if (this.indenting) { this.indent(); } else if (!inline[tag]) { this.newline(); this.indent(); } this.buff.push(''); }, visitText: function (text,notTrans){ if (this.indenting) { this.indent(); } // if(!notTrans){ // text = text.replace(/ /g, ' ').replace(/[ ][ ]+/g, function (m){ // return new Array(m.length + 1).join(' '); // }).replace(/(?:^ )|(?: $)/g, ' '); // } text = text.replace(/ /g, ' '); this.buff.push(text); }, visitComment: function (text){ if (this.indenting) { this.indent(); } this.buff.push(''); } }; 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 formatter = new SourceFormater(opt.source); var sourceMode = false; var sourceEditor; 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 = me.getContent, bakAddress; 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;'; var content = formatter.format(me.hasContents() ? me.getContent() : ''); sourceEditor = createSourceEditor(me.iframe.parentNode); sourceEditor.setContent(content); setTimeout(function (){ sourceEditor.select(); me.addListener('fullscreenchanged', function(){ try{ sourceEditor.getCodeMirror().refresh() }catch(e){} }); }); //重置getContent,源码模式下取值也能是最新的数据 me.getContent = function (){ var cont = sourceEditor.getContent() || '

' + (browser.ie ? '' : '
')+'

'; return cont.replace(/>[\n\r\t]+([ ]{4})+/g,'>').replace(/[\n\r\t]+([ ]{4})+[\n\r\t]+<'); }; } else { me.iframe.style.cssText = bakCssText; var cont = sourceEditor.getContent() || '

' + (browser.ie ? '' : '
')+'

'; cont = cont.replace(/>[\n\r\t]+([ ]{4})+/g,'>').replace(/[\n\r\t]+([ ]{4})+[\n\r\t]+<'); me.setContent(cont); sourceEditor.dispose(); sourceEditor = null; //还原getContent方法 me.getContent = oldGetContent; var first = me.body.firstChild; //trace:1106 都删除空了,下边会报错,所以补充一个p占位 if(!first){ me.body.innerHTML = '

'+(browser.ie?'':'
')+'

'; 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(); domUtils.remove(input); }); }); }else{ //ie下有可能报错,比如在代码顶头的情况 try{ me.selection.getRange().moveToAddress(bakAddress).select(); }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" }); }); } }; })();