305 Star 1.5K Fork 291

GVPNotadd/Neditor

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
source.js 10.72 KB
一键复制 编辑 原始数据 按行查看 历史
/**
* 源码编辑插件
* @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;
},
focus: function (){
textarea.focus();
},
blur: function (){
textarea.blur();
}
};
},
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;
},
focus: function (){
codeEditor.focus();
},
blur: function (){
// codeEditor.blur();
// since codemirror not support blur()
codeEditor.setOption('readOnly', true);
codeEditor.setOption('readOnly', false);
}
};
}
};
UE.plugins["source"] = function() {
var me = this;
var opt = this.options;
var sourceMode = false;
var sourceEditor;
var orgSetContent;
var orgFocus;
var orgBlur;
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(/&nbsp;/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>"
);
};
orgFocus = me.focus;
orgBlur = me.blur;
me.focus = function(){
sourceEditor.focus();
};
me.blur = function(){
orgBlur.call(me);
sourceEditor.blur();
};
} 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;
me.focus = orgFocus;
me.blur = orgBlur;
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"
});
});
}
};
})();
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
JavaScript
1
https://gitee.com/notadd/neditor.git
git@gitee.com:notadd/neditor.git
notadd
neditor
Neditor
master

搜索帮助