123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352 |
- ///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<children.length; i++) {
- this.visitNode(children[i]);
- }
- },
- visitTag: function (tag, attrs, selfClosing){
- if (this.indenting) {
- this.indent();
- } else if (!inline[tag]) { // todo: 去掉a, 因为dtd的inline里面没有a
- this.newline();
- this.indent();
- }
- this.buff.push('<', tag);
- var attrPart = printAttrs(attrs);
- if (attrPart) {
- this.buff.push(' ', attrPart);
- }
- if (selfClosing) {
- this.buff.push(this.selfClosingEnd);
- if (tag == 'br') {
- this.newline();
- }
- } else {
- this.buff.push('>');
- 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('</', tag, '>');
- },
- 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('<!--', text, '-->');
- }
- };
- 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() || '<p>' + (browser.ie ? '' : '<br/>')+'</p>';
- return cont.replace(/>[\n\r\t]+([ ]{4})+/g,'>').replace(/[\n\r\t]+([ ]{4})+</g,'<').replace(/>[\n\r\t]+</g,'><');
- };
- } else {
- me.iframe.style.cssText = bakCssText;
- var cont = sourceEditor.getContent() || '<p>' + (browser.ie ? '' : '<br/>')+'</p>';
- cont = cont.replace(/>[\n\r\t]+([ ]{4})+/g,'>').replace(/[\n\r\t]+([ ]{4})+</g,'<').replace(/>[\n\r\t]+</g,'><');
- 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();
- 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"
- });
- });
- }
- };
- })();
|