');
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('');
}
};
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 options = {
mode: "text/html",
tabMode: "indent",
lineNumbers: true,
lineWrapping:true
};
var codeEditor = window.CodeMirror(holder, options);
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 {
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 = opt.sourceEditor || 'codemirror';
function createSourceEditor(holder){
return sourceEditors[opt.sourceEditor == 'codemirror' && window.CodeMirror ? 'codemirror' : 'textarea'](me, holder);
}
var bakCssText;
me.commands['source'] = {
execCommand: function (){
sourceMode = !sourceMode;
if (sourceMode) {
me.undoManger && me.undoManger.save();
this.currentSelectedArr && domUtils.clearSelectedArr(this.currentSelectedArr);
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();
});
} 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;
setTimeout(function(){
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();
while(first && first.firstChild){
first = first.firstChild;
}
var range = me.selection.getRange();
if(first.nodeType == 3 || dtd.$empty[first.tagName]){
range.setStartBefore(first)
}else{
range.setStart(first,0);
}
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;
range.setCursor(false,true);
domUtils.remove(input)
})
})
}else{
range.setCursor(false,true);
}
})
}
this.fireEvent('sourcemodechanged', sourceMode);
},
queryCommandState: function (){
return sourceMode|0;
}
};
var oldQueryCommandState = me.queryCommandState;
me.queryCommandState = function (cmdName){
cmdName = cmdName.toLowerCase();
if (sourceMode) {
return cmdName == 'source' ? 1 : -1;
}
return oldQueryCommandState.apply(this, arguments);
};
//解决在源码模式下getContent不能得到最新的内容问题
var oldGetContent = me.getContent;
me.getContent = function (){
if(sourceMode && sourceEditor ){
var html = sourceEditor.getContent();
if (this.serialize) {
var node = this.serialize.parseHTML(html);
node = this.serialize.filter(node);
html = this.serialize.toHTML(node);
}
return html;
}else{
return oldGetContent.apply(this, arguments)
}
};
if(opt.sourceEditor == "codemirror"){
me.addListener("ready",function(){
utils.loadFile(document,{
src : opt.codeMirrorJsUrl || opt.UEDITOR_HOME_URL + "third-party/codemirror2.15/codemirror.js",
tag : "script",
type : "text/javascript",
defer : "defer"
});
utils.loadFile(document,{
tag : "link",
rel : "stylesheet",
type : "text/css",
href : opt.codeMirrorCssUrl || opt.UEDITOR_HOME_URL + "third-party/codemirror2.15/codemirror.css"
});
});
}
};
})();
///import core
///commands 快捷键
///commandsName ShortCutKeys
///commandsTitle 快捷键
//配置快捷键
UE.plugins['shortcutkeys'] = function(){
var me = this,
shortcutkeys = {
"ctrl+66" : "Bold" ,//^B
"ctrl+90" : "Undo" ,//undo
"ctrl+89" : "Redo", //redo
"ctrl+73" : "Italic", //^I
"ctrl+85" : "Underline" ,//^U
"ctrl+shift+67" : "removeformat", //清除格式
"ctrl+shift+76" : "justify:left", //居左
"ctrl+shift+82" : "justify:right", //居右
"ctrl+65" : "selectAll",
"ctrl+13" : "autosubmit"//手动提交
// ,"9" : "indent" //tab
};
me.addListener('keydown',function(type,e){
var keyCode = e.keyCode || e.which,value;
for ( var i in shortcutkeys ) {
if ( /^(ctrl)(\+shift)?\+(\d+)$/.test( i.toLowerCase() ) || /^(\d+)$/.test( i ) ) {
if ( ( (RegExp.$1 == 'ctrl' ? (e.ctrlKey||e.metaKey) : 0)
&& (RegExp.$2 != "" ? e[RegExp.$2.slice(1) + "Key"] : 1)
&& keyCode == RegExp.$3
) ||
keyCode == RegExp.$1
){
value = shortcutkeys[i].split(':');
me.execCommand( value[0],value[1]);
domUtils.preventDefault(e)
}
}
}
});
};
///import core
///import plugins/undo.js
///commands 设置回车标签p或br
///commandsName EnterKey
///commandsTitle 设置回车标签p或br
/**
* @description 处理回车
* @author zhanyi
*/
UE.plugins['enterkey'] = function() {
var hTag,
me = this,
tag = me.options.enterTag;
me.addListener('keyup', function(type, evt) {
var keyCode = evt.keyCode || evt.which;
if (keyCode == 13) {
var range = me.selection.getRange(),
start = range.startContainer,
doSave;
//修正在h1-h6里边回车后不能嵌套p的问题
if (!browser.ie) {
if (/h\d/i.test(hTag)) {
if (browser.gecko) {
var h = domUtils.findParentByTagName(start, [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6','blockquote'], true);
if (!h) {
me.document.execCommand('formatBlock', false, '');
doSave = 1;
}
} else {
//chrome remove div
if (start.nodeType == 1) {
var tmp = me.document.createTextNode(''),div;
range.insertNode(tmp);
div = domUtils.findParentByTagName(tmp, 'div', true);
if (div) {
var p = me.document.createElement('p');
while (div.firstChild) {
p.appendChild(div.firstChild);
}
div.parentNode.insertBefore(p, div);
domUtils.remove(div);
range.setStartBefore(tmp).setCursor();
doSave = 1;
}
domUtils.remove(tmp);
}
}
if (me.undoManger && doSave) {
me.undoManger.save()
}
}
}
setTimeout(function() {
me.selection.getRange().scrollToView(me.autoHeightEnabled, me.autoHeightEnabled ? domUtils.getXY(me.iframe).y : 0);
}, 50)
}
});
me.addListener('keydown', function(type, evt) {
var keyCode = evt.keyCode || evt.which;
if (keyCode == 13) {//回车
if (me.undoManger) {
me.undoManger.save()
}
hTag = '';
var range = me.selection.getRange();
if (!range.collapsed) {
//跨td不能删
var start = range.startContainer,
end = range.endContainer,
startTd = domUtils.findParentByTagName(start, 'td', true),
endTd = domUtils.findParentByTagName(end, 'td', true);
if (startTd && endTd && startTd !== endTd || !startTd && endTd || startTd && !endTd) {
evt.preventDefault ? evt.preventDefault() : ( evt.returnValue = false);
return;
}
}
me.currentSelectedArr && domUtils.clearSelectedArr(me.currentSelectedArr);
if (tag == 'p') {
if (!browser.ie) {
start = domUtils.findParentByTagName(range.startContainer, ['ol','ul','p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6','blockquote'], true);
if (!start) {
me.document.execCommand('formatBlock', false, '
');
if (browser.gecko) {
range = me.selection.getRange();
start = domUtils.findParentByTagName(range.startContainer, 'p', true);
start && domUtils.removeDirtyAttr(start);
}
} else {
hTag = start.tagName;
start.tagName.toLowerCase() == 'p' && browser.gecko && domUtils.removeDirtyAttr(start);
}
}
} else {
evt.preventDefault ? evt.preventDefault() : ( evt.returnValue = false);
if (!range.collapsed) {
range.deleteContents();
start = range.startContainer;
if (start.nodeType == 1 && (start = start.childNodes[range.startOffset])) {
while (start.nodeType == 1) {
if (dtd.$empty[start.tagName]) {
range.setStartBefore(start).setCursor();
if (me.undoManger) {
me.undoManger.save()
}
return false;
}
if (!start.firstChild) {
var br = range.document.createElement('br');
start.appendChild(br);
range.setStart(start, 0).setCursor();
if (me.undoManger) {
me.undoManger.save()
}
return false;
}
start = start.firstChild
}
if (start === range.startContainer.childNodes[range.startOffset]) {
br = range.document.createElement('br');
range.insertNode(br).setCursor();
} else {
range.setStart(start, 0).setCursor();
}
} else {
br = range.document.createElement('br');
range.insertNode(br).setStartAfter(br).setCursor();
}
} else {
br = range.document.createElement('br');
range.insertNode(br);
var parent = br.parentNode;
if (parent.lastChild === br) {
br.parentNode.insertBefore(br.cloneNode(true), br);
range.setStartBefore(br)
} else {
range.setStartAfter(br)
}
range.setCursor();
}
}
}
});
};
/*
* 处理特殊键的兼容性问题
*/
UE.plugins['keystrokes'] = function() {
var me = this,
flag = 0,
keys = domUtils.keys,
trans = {
'B' : 'strong',
'I' : 'em',
'FONT' : 'span'
},
sizeMap = [0, 10, 12, 16, 18, 24, 32, 48],
listStyle = {
'OL':['decimal','lower-alpha','lower-roman','upper-alpha','upper-roman'],
'UL':[ 'circle','disc','square']
};
me.addListener('keydown', function(type, evt) {
var keyCode = evt.keyCode || evt.which;
if(this.selectAll){
this.selectAll = false;
if((keyCode == 8 || keyCode == 46)){
me.undoManger && me.undoManger.save();
//trace:1633
me.body.innerHTML = '
'+(browser.ie ? '' : '
')+'
';
new dom.Range(me.document).setStart(me.body.firstChild,0).setCursor(false,true);
me.undoManger && me.undoManger.save();
//todo 对性能会有影响
browser.ie && me._selectionChange();
domUtils.preventDefault(evt);
return;
}
}
//处理backspace/del
if (keyCode == 8 ) {//|| keyCode == 46
var range = me.selection.getRange(),
tmpRange,
start,end;
//当删除到body最开始的位置时,会删除到body,阻止这个动作
if(range.collapsed){
start = range.startContainer;
//有可能是展位符号
if(domUtils.isWhitespace(start)){
start = start.parentNode;
}
if(domUtils.isEmptyNode(start) && start === me.body.firstChild){
if(start.tagName != 'P'){
p = me.document.createElement('p');
me.body.insertBefore(p,start);
domUtils.fillNode(me.document,p);
range.setStart(p,0).setCursor(false,true);
//trace:1645
domUtils.remove(start);
}
domUtils.preventDefault(evt);
return;
}
}
if (range.collapsed && range.startContainer.nodeType == 3 && range.startContainer.nodeValue.replace(new RegExp(domUtils.fillChar, 'g'), '').length == 0) {
range.setStartBefore(range.startContainer).collapse(true)
}
//解决选中control元素不能删除的问题
if (start = range.getClosedNode()) {
me.undoManger && me.undoManger.save();
range.setStartBefore(start);
domUtils.remove(start);
range.setCursor();
me.undoManger && me.undoManger.save();
domUtils.preventDefault(evt);
return;
}
//阻止在table上的删除
if (!browser.ie) {
start = domUtils.findParentByTagName(range.startContainer, 'table', true);
end = domUtils.findParentByTagName(range.endContainer, 'table', true);
if (start && !end || !start && end || start !== end) {
evt.preventDefault();
return;
}
//表格里回车,删除时,光标被定位到了p外边,导致多次删除才能到上一行,这里的处理忘记是为什么,暂时注视掉
//解决trace:1966的问题
// if (browser.webkit && range.collapsed && start) {
// tmpRange = range.cloneRange().txtToElmBoundary();
// start = tmpRange.startContainer;
// debugger
// if (domUtils.isBlockElm(start) && !dtd.$tableContent[start.tagName] && !domUtils.getChildCount(start, function(node) {
// return node.nodeType == 1 ? node.tagName !== 'BR' : 1;
// })) {
//
// tmpRange.setStartBefore(start).setCursor();
// domUtils.remove(start, true);
// evt.preventDefault();
// return;
// }
// }
}
if (me.undoManger) {
if (!range.collapsed) {
me.undoManger.save();
flag = 1;
}
}
}
//处理tab键的逻辑
if (keyCode == 9) {
range = me.selection.getRange();
me.undoManger && me.undoManger.save();
for (var i = 0,txt = '',tabSize = me.options.tabSize|| 4,tabNode = me.options.tabNode || ' '; i < tabSize; i++) {
txt += tabNode;
}
var span = me.document.createElement('span');
span.innerHTML = txt;
if (range.collapsed) {
var li = domUtils.findParentByTagName(range.startContainer, 'li', true);
if (li && domUtils.isStartInblock(range)) {
bk = range.createBookmark();
var parentLi = li.parentNode,
list = me.document.createElement(parentLi.tagName);
var index = utils.indexOf(listStyle[list.tagName], domUtils.getComputedStyle(parentLi, 'list-style-type'));
index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
domUtils.setStyle(list, 'list-style-type', listStyle[list.tagName][index]);
parentLi.insertBefore(list, li);
list.appendChild(li);
range.moveToBookmark(bk).select()
} else
range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
} else {
//处理table
start = domUtils.findParentByTagName(range.startContainer, 'table', true);
end = domUtils.findParentByTagName(range.endContainer, 'table', true);
if (start || end) {
evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
return
}
//处理列表 再一个list里处理
start = domUtils.findParentByTagName(range.startContainer, ['ol','ul'], true);
end = domUtils.findParentByTagName(range.endContainer, ['ol','ul'], true);
if (start && end && start === end) {
var bk = range.createBookmark();
start = domUtils.findParentByTagName(range.startContainer, 'li', true);
end = domUtils.findParentByTagName(range.endContainer, 'li', true);
//在开始单独处理
if (start === start.parentNode.firstChild) {
var parentList = me.document.createElement(start.parentNode.tagName);
start.parentNode.parentNode.insertBefore(parentList, start.parentNode);
parentList.appendChild(start.parentNode);
} else {
parentLi = start.parentNode,
list = me.document.createElement(parentLi.tagName);
index = utils.indexOf(listStyle[list.tagName], domUtils.getComputedStyle(parentLi, 'list-style-type'));
index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
domUtils.setStyle(list, 'list-style-type', listStyle[list.tagName][index]);
start.parentNode.insertBefore(list, start);
var nextLi;
while (start !== end) {
nextLi = start.nextSibling;
list.appendChild(start);
start = nextLi;
}
list.appendChild(end);
}
range.moveToBookmark(bk).select();
} else {
if (start || end) {
evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
return
}
//普通的情况
start = domUtils.findParent(range.startContainer, filterFn);
end = domUtils.findParent(range.endContainer, filterFn);
if (start && end && start === end) {
range.deleteContents();
range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
} else {
var bookmark = range.createBookmark(),
filterFn = function(node) {
return domUtils.isBlockElm(node);
};
range.enlarge(true);
var bookmark2 = range.createBookmark(),
current = domUtils.getNextDomNode(bookmark2.start, false, filterFn);
while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
current.insertBefore(span.cloneNode(true).firstChild, current.firstChild);
current = domUtils.getNextDomNode(current, false, filterFn);
}
range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select();
}
}
}
me.undoManger && me.undoManger.save();
evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
}
//trace:1634
//ff的del键在容器空的时候,也会删除
if(browser.gecko && keyCode == 46){
range = me.selection.getRange();
if(range.collapsed){
start = range.startContainer;
if(domUtils.isEmptyBlock(start)){
var parent = start.parentNode;
while(domUtils.getChildCount(parent) == 1 && !domUtils.isBody(parent)){
start = parent;
parent = parent.parentNode;
}
if(start === parent.lastChild)
evt.preventDefault();
return;
}
}
}
});
me.addListener('keyup', function(type, evt) {
var keyCode = evt.keyCode || evt.which;
//修复ie/chrome x| 当点退格后在输入文字后会出现 x
if (!browser.gecko && !keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
range = me.selection.getRange();
if (range.collapsed) {
var start = range.startContainer,
isFixed = 0;
while (!domUtils.isBlockElm(start)) {
if (start.nodeType == 1 && utils.indexOf(['FONT','B','I'], start.tagName) != -1) {
var tmpNode = me.document.createElement(trans[start.tagName]);
if (start.tagName == 'FONT') {
//chrome only remember color property
tmpNode.style.cssText = (start.getAttribute('size') ? 'font-size:' + (sizeMap[start.getAttribute('size')] || 12) + 'px' : '')
+ ';' + (start.getAttribute('color') ? 'color:' + start.getAttribute('color') : '')
+ ';' + (start.getAttribute('face') ? 'font-family:' + start.getAttribute('face') : '')
+ ';' + start.style.cssText;
}
while (start.firstChild) {
tmpNode.appendChild(start.firstChild)
}
start.parentNode.insertBefore(tmpNode, start);
domUtils.remove(start);
if (!isFixed) {
range.setEnd(tmpNode, tmpNode.childNodes.length).collapse(true)
}
start = tmpNode;
isFixed = 1;
}
start = start.parentNode;
}
isFixed && range.select()
}
}
if (keyCode == 8 ) {//|| keyCode == 46
//针对ff下在列表首行退格,不能删除空格行的问题
if(browser.gecko){
for(var i=0,li,lis = domUtils.getElementsByTagName(this.body,'li');li=lis[i++];){
if(domUtils.isEmptyNode(li) && !li.previousSibling){
var liOfPn = li.parentNode;
domUtils.remove(li);
if(domUtils.isEmptyNode(liOfPn)){
domUtils.remove(liOfPn)
}
}
}
}
var range,start,parent,
tds = this.currentSelectedArr;
if (tds && tds.length > 0) {
for (var i = 0,ti; ti = tds[i++];) {
ti.innerHTML = browser.ie ? ( browser.version < 9 ? '' : '' ) : '
';
}
range = new dom.Range(this.document);
range.setStart(tds[0], 0).setCursor();
if (flag) {
me.undoManger.save();
flag = 0;
}
//阻止chrome执行默认的动作
if (browser.webkit) {
evt.preventDefault();
}
return;
}
range = me.selection.getRange();
//ctrl+a 后全部删除做处理
//
// if (domUtils.isEmptyBlock(me.body) && !range.startOffset) {
// //trace:1633
// me.body.innerHTML = ''+(browser.ie ? ' ' : '
')+'
';
// range.setStart(me.body.firstChild,0).setCursor(false,true);
// me.undoManger && me.undoManger.save();
// //todo 对性能会有影响
// browser.ie && me._selectionChange();
// return;
// }
//处理删除不干净的问题
start = range.startContainer;
if(domUtils.isWhitespace(start)){
start = start.parentNode
}
//标志位防止空的p无法删除
var removeFlag = 0;
while (start.nodeType == 1 && domUtils.isEmptyNode(start) && dtd.$removeEmpty[start.tagName]) {
removeFlag = 1;
parent = start.parentNode;
domUtils.remove(start);
start = parent;
}
if ( removeFlag && start.nodeType == 1 && domUtils.isEmptyNode(start)) {
//ie下的问题,虽然没有了相应的节点但一旦你输入文字还是会自动把删除的节点加上,
if (browser.ie) {
var span = range.document.createElement('span');
start.appendChild(span);
range.setStart(start,0).setCursor();
//for ie
li = domUtils.findParentByTagName(start,'li',true);
if(li){
var next = li.nextSibling;
while(next){
if(domUtils.isEmptyBlock(next)){
li = next;
next = next.nextSibling;
domUtils.remove(li);
continue;
}
break;
}
}
} else {
start.innerHTML = '
';
range.setStart(start, 0).setCursor(false,true);
}
setTimeout(function() {
if (browser.ie) {
domUtils.remove(span);
}
if (flag) {
me.undoManger.save();
flag = 0;
}
}, 0)
} else {
if (flag) {
me.undoManger.save();
flag = 0;
}
}
}
})
};
///import core
///commands 修复chrome下图片不能点击的问题
///commandsName FixImgClick
///commandsTitle 修复chrome下图片不能点击的问题
//修复chrome下图片不能点击的问题
//todo 可以改大小
UE.plugins['fiximgclick'] = function() {
var me = this;
if ( browser.webkit ) {
me.addListener( 'click', function( type, e ) {
if ( e.target.tagName == 'IMG' ) {
var range = new dom.Range( me.document );
range.selectNode( e.target ).select();
}
} )
}
};
///import core
///commands 为非ie浏览器自动添加a标签
///commandsName AutoLink
///commandsTitle 自动增加链接
/**
* @description 为非ie浏览器自动添加a标签
* @author zhanyi
*/
UE.plugins['autolink'] = function() {
var cont = 0;
if (browser.ie) {
return;
}
var me = this;
me.addListener('reset',function(){
cont = 0;
});
me.addListener('keydown', function(type, evt) {
var keyCode = evt.keyCode || evt.which;
if (keyCode == 32 || keyCode == 13) {
var sel = me.selection.getNative(),
range = sel.getRangeAt(0).cloneRange(),
offset,
charCode;
var start = range.startContainer;
while (start.nodeType == 1 && range.startOffset > 0) {
start = range.startContainer.childNodes[range.startOffset - 1];
if (!start)
break;
range.setStart(start, start.nodeType == 1 ? start.childNodes.length : start.nodeValue.length);
range.collapse(true);
start = range.startContainer;
}
do{
if (range.startOffset == 0) {
start = range.startContainer.previousSibling;
while (start && start.nodeType == 1) {
start = start.lastChild;
}
if (!start || domUtils.isFillChar(start))
break;
offset = start.nodeValue.length;
} else {
start = range.startContainer;
offset = range.startOffset;
}
range.setStart(start, offset - 1);
charCode = range.toString().charCodeAt(0);
} while (charCode != 160 && charCode != 32);
if (range.toString().replace(new RegExp(domUtils.fillChar, 'g'), '').match(/(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i)) {
while(range.toString().length){
if(/^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i.test(range.toString())){
break;
}
try{
range.setStart(range.startContainer,range.startOffset+1)
}catch(e){
//trace:2121
var start = range.startContainer;
while(!(next = start.nextSibling)){
if(domUtils.isBody(start)){
return;
}
start = start.parentNode;
}
range.setStart(next,0)
}
}
var a = me.document.createElement('a'),text = me.document.createTextNode(' '),href;
me.undoManger && me.undoManger.save();
a.appendChild(range.extractContents());
a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g,'');
href = a.getAttribute("href").replace(new RegExp(domUtils.fillChar,'g'),'');
href = /^(?:https?:\/\/)/ig.test(href) ? href : "http://"+ href;
a.setAttribute('data_ue_src',href);
a.href = href;
range.insertNode(a);
a.parentNode.insertBefore(text, a.nextSibling);
range.setStart(text, 0);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
me.undoManger && me.undoManger.save();
}
}
})
};
///import core
///commands 当输入内容超过编辑器高度时,编辑器自动增高
///commandsName AutoHeight,autoHeightEnabled
///commandsTitle 自动增高
/**
* @description 自动伸展
* @author zhanyi
*/
UE.plugins['autoheight'] = function () {
var me = this;
//提供开关,就算加载也可以关闭
me.autoHeightEnabled = me.options.autoHeightEnabled !== false ;
if (!me.autoHeightEnabled)return;
var bakOverflow,
span, tmpNode,
lastHeight = 0,
currentHeight,
timer;
function adjustHeight() {
clearTimeout(timer);
timer = setTimeout(function () {
if (me.queryCommandState('source') != 1) {
if (!span) {
span = me.document.createElement('span');
//trace:1764
span.style.cssText = 'display:block;width:0;margin:0;padding:0;border:0;clear:both;';
span.innerHTML = '.';
}
tmpNode = span.cloneNode(true);
me.body.appendChild(tmpNode);
currentHeight = Math.max(domUtils.getXY(tmpNode).y + tmpNode.offsetHeight, me.options.minFrameHeight);
if (currentHeight != lastHeight) {
me.setHeight(currentHeight);
lastHeight = currentHeight;
}
domUtils.remove(tmpNode);
}
}, 50)
}
me.addListener('destroy', function () {
me.removeListener('contentchange', adjustHeight);
me.removeListener('keyup', adjustHeight);
me.removeListener('mouseup', adjustHeight);
});
me.enableAutoHeight = function () {
if(!me.autoHeightEnabled)return;
var doc = me.document;
me.autoHeightEnabled = true;
bakOverflow = doc.body.style.overflowY;
doc.body.style.overflowY = 'hidden';
me.addListener('contentchange', adjustHeight);
me.addListener('keyup', adjustHeight);
me.addListener('mouseup', adjustHeight);
//ff不给事件算得不对
setTimeout(function () {
adjustHeight();
}, browser.gecko ? 100 : 0);
me.fireEvent('autoheightchanged', me.autoHeightEnabled);
};
me.disableAutoHeight = function () {
me.body.style.overflowY = bakOverflow || '';
me.removeListener('contentchange', adjustHeight);
me.removeListener('keyup', adjustHeight);
me.removeListener('mouseup', adjustHeight);
me.autoHeightEnabled = false;
me.fireEvent('autoheightchanged', me.autoHeightEnabled);
};
me.addListener('ready', function () {
me.enableAutoHeight();
//trace:1764
var timer;
domUtils.on(browser.ie ? me.body : me.document,browser.webkit ? 'dragover' : 'drop',function(){
clearTimeout(timer);
timer = setTimeout(function(){
adjustHeight()
},100)
});
});
};
///import core
///commands 悬浮工具栏
///commandsName AutoFloat,autoFloatEnabled
///commandsTitle 悬浮工具栏
/*
* modified by chengchao01
*
* 注意: 引入此功能后,在IE6下会将body的背景图片覆盖掉!
*/
UE.plugins['autofloat'] = function() {
var me = this,
optsAutoFloatEnabled = me.options.autoFloatEnabled !== false;
//如果不固定toolbar的位置,则直接退出
if(!optsAutoFloatEnabled){
return;
}
var uiUtils = UE.ui.uiUtils,
LteIE6 = browser.ie && browser.version <= 6,
quirks = browser.quirks;
function checkHasUI(editor){
if(!editor.ui){
alert('autofloat插件功能依赖于UEditor UI\nautofloat定义位置: _src/plugins/autofloat.js');
throw({
name: '未包含UI文件',
message: 'autofloat功能依赖于UEditor UI。autofloat定义位置: _src/plugins/autofloat.js'
});
}
return 1;
}
function fixIE6FixedPos(){
var docStyle = document.body.style;
docStyle.backgroundImage = 'url("about:blank")';
docStyle.backgroundAttachment = 'fixed';
}
var bakCssText,
placeHolder = document.createElement('div'),
toolbarBox,orgTop,
getPosition,
flag =true; //ie7模式下需要偏移
function setFloating(){
var toobarBoxPos = domUtils.getXY(toolbarBox),
origalFloat = domUtils.getComputedStyle(toolbarBox,'position'),
origalLeft = domUtils.getComputedStyle(toolbarBox,'left');
toolbarBox.style.width = toolbarBox.offsetWidth + 'px';
toolbarBox.style.zIndex = me.options.zIndex * 1 + 1;
toolbarBox.parentNode.insertBefore(placeHolder, toolbarBox);
if (LteIE6 || quirks) {
if(toolbarBox.style.position != 'absolute'){
toolbarBox.style.position = 'absolute';
}
toolbarBox.style.top = (document.body.scrollTop||document.documentElement.scrollTop) - orgTop + 'px';
} else {
if (browser.ie7Compat && flag) {
flag = false;
toolbarBox.style.left = domUtils.getXY(toolbarBox).x - document.documentElement.getBoundingClientRect().left+2 + 'px';
}
if(toolbarBox.style.position != 'fixed'){
toolbarBox.style.position = 'fixed';
toolbarBox.style.top = '0';
((origalFloat == 'absolute' || origalFloat == 'relative') && parseFloat(origalLeft)) && (toolbarBox.style.left = toobarBoxPos.x + 'px');
}
}
}
function unsetFloating(){
flag = true;
if(placeHolder.parentNode)
placeHolder.parentNode.removeChild(placeHolder);
toolbarBox.style.cssText = bakCssText;
}
function updateFloating(){
var rect3 = getPosition(me.container);
if (rect3.top < 0 && rect3.bottom - toolbarBox.offsetHeight > 0) {
setFloating();
}else{
unsetFloating();
}
}
var defer_updateFloating = utils.defer(function(){
updateFloating();
},browser.ie ? 200 : 100,true);
me.addListener('destroy',function(){
domUtils.un(window, ['scroll','resize'], updateFloating);
me.removeListener('keydown', defer_updateFloating);
});
me.addListener('ready', function(){
if(checkHasUI(me)){
getPosition = uiUtils.getClientRect;
toolbarBox = me.ui.getDom('toolbarbox');
orgTop = getPosition(toolbarBox).top;
bakCssText = toolbarBox.style.cssText;
placeHolder.style.height = toolbarBox.offsetHeight + 'px';
if(LteIE6){
fixIE6FixedPos();
}
me.addListener('autoheightchanged', function (t, enabled){
if (enabled) {
domUtils.on(window, ['scroll','resize'], updateFloating);
me.addListener('keydown', defer_updateFloating);
} else {
domUtils.un(window, ['scroll','resize'], updateFloating);
me.removeListener('keydown', defer_updateFloating);
}
});
me.addListener('beforefullscreenchange', function (t, enabled){
if (enabled) {
unsetFloating();
}
});
me.addListener('fullscreenchanged', function (t, enabled){
if (!enabled) {
updateFloating();
}
});
me.addListener('sourcemodechanged', function (t, enabled){
setTimeout(function (){
updateFloating();
});
});
}
})
};
///import core
///import plugins/inserthtml.js
///commands 插入代码
///commandsName HighlightCode
///commandsTitle 插入代码
///commandsDialog dialogs\code\code.html
UE.plugins['highlight'] = function() {
var me = this;
if(!/highlightcode/i.test(me.options.toolbars.join('')))return;
me.commands['highlightcode'] = {
execCommand: function (cmdName, code, syntax) {
if(code && syntax){
var pre = document.createElement("pre");
pre.className = "brush: "+syntax+";toolbar:false;";
pre.style.display = "";
pre.appendChild(document.createTextNode(code));
document.body.appendChild(pre);
if(me.queryCommandState("highlightcode")){
me.execCommand("highlightcode");
}
me.execCommand('inserthtml', SyntaxHighlighter.highlight(pre,null,true),true);
var div = me.document.getElementById(SyntaxHighlighter.getHighlighterDivId());
div.setAttribute('highlighter',pre.className);
domUtils.remove(pre);
adjustHeight()
}else{
var range = this.selection.getRange(),
start = domUtils.findParentByTagName(range.startContainer, 'table', true),
end = domUtils.findParentByTagName(range.endContainer, 'table', true),
codediv;
if(start && end && start === end && start.parentNode.className.indexOf("syntaxhighlighter")>-1){
codediv = start.parentNode;
if(domUtils.isBody(codediv.parentNode)){
var p = me.document.createElement('p');
p.innerHTML = browser.ie ? '' : '
';
me.body.insertBefore(p,codediv);
range.setStart(p,0)
}else{
range.setStartBefore(codediv)
}
range.setCursor();
domUtils.remove(codediv);
}
}
},
queryCommandState: function(){
var range = this.selection.getRange(),start,end;
range.adjustmentBoundary();
start = domUtils.findParent(range.startContainer,function(node){
return node.nodeType == 1 && node.tagName == 'DIV' && domUtils.hasClass(node,'syntaxhighlighter')
},true);
end = domUtils.findParent(range.endContainer,function(node){
return node.nodeType == 1 && node.tagName == 'DIV' && domUtils.hasClass(node,'syntaxhighlighter')
},true);
return start && end && start == end ? 1 : 0;
}
};
me.addListener('beforeselectionchange',function(){
me.highlight = me.queryCommandState('highlightcode');
});
me.addListener('afterselectionchange',function(){
me.highlight = 0;
});
me.addListener("ready",function(){
//避免重复加载高亮文件
if(typeof XRegExp == "undefined"){
var obj = {
id : "syntaxhighlighter_js",
src : me.options.highlightJsUrl || me.options.UEDITOR_HOME_URL + "third-party/SyntaxHighlighter/shCore.js",
tag : "script",
type : "text/javascript",
defer : "defer"
};
utils.loadFile(document,obj,function(){
changePre();
});
}
if(!me.document.getElementById("syntaxhighlighter_css")){
var obj = {
id : "syntaxhighlighter_css",
tag : "link",
rel : "stylesheet",
type : "text/css",
href : me.options.highlightCssUrl ||me.options.UEDITOR_HOME_URL + "third-party/SyntaxHighlighter/shCoreDefault.css"
};
utils.loadFile(me.document,obj);
}
});
me.addListener("beforegetcontent",function(type,cmd){
for(var i=0,di,divs=domUtils.getElementsByTagName(me.body,'div');di=divs[i++];){
if(di.className == 'container'){
var pN = di.parentNode;
while(pN){
if(pN.tagName == 'DIV' && /highlighter/.test(pN.id)){
break;
}
pN = pN.parentNode;
}
if(!pN)return;
var pre = me.document.createElement('pre');
for(var str=[],c=0,ci;ci=di.childNodes[c++];){
str.push(ci[browser.ie?'innerText':'textContent']);
}
pre.appendChild(me.document.createTextNode(str.join('\n')));
pre.className = pN.getAttribute('highlighter');
pN.parentNode.insertBefore(pre,pN);
domUtils.remove(pN);
}
}
});
me.addListener("aftergetcontent",function(type,cmd){
changePre();
});
function adjustHeight(){
setTimeout(function(){
var div = me.document.getElementById(SyntaxHighlighter.getHighlighterDivId());
if(div){
var tds = div.getElementsByTagName('td');
for(var i=0,li,ri;li=tds[0].childNodes[i];i++){
ri = tds[1].firstChild.childNodes[i];
//trace:1949
if(ri){
ri.style.height = li.style.height = ri.offsetHeight + 'px';
}
}
}
});
}
function changePre(){
for(var i=0,pr,pres = domUtils.getElementsByTagName(me.document,"pre");pr=pres[i++];){
if(pr.className.indexOf("brush")>-1){
var pre = document.createElement("pre"),txt,div;
pre.className = pr.className;
pre.style.display = "none";
pre.appendChild(document.createTextNode(pr[browser.ie?'innerText':'textContent']));
document.body.appendChild(pre);
try{
txt = SyntaxHighlighter.highlight(pre,null,true);
}catch(e){
domUtils.remove(pre);
return ;
}
div = me.document.createElement("div");
div.innerHTML = txt;
div.firstChild.setAttribute('highlighter',pre.className);
pr.parentNode.insertBefore(div.firstChild,pr);
domUtils.remove(pre);
domUtils.remove(pr);
adjustHeight()
}
}
}
me.addListener("aftersetcontent",function(){
changePre();
});
//全屏时,重新算一下宽度
me.addListener('fullscreenchanged',function(){
var div = domUtils.getElementsByTagName(me.document,'div');
for(var j=0,di;di=div[j++];){
if(/^highlighter/.test(di.id)){
var tds = di.getElementsByTagName('td');
for(var i=0,li,ri;li=tds[0].childNodes[i];i++){
ri = tds[1].firstChild.childNodes[i];
ri.style.height = li.style.height = ri.offsetHeight + 'px';
}
}
}
})
};
///import core
///commands 定制过滤规则
///commandsName Serialize
///commandsTitle 定制过滤规则
UE.plugins['serialize'] = function () {
var ie = browser.ie,
version = browser.version;
function ptToPx(value){
return /pt/.test(value) ? value.replace( /([\d.]+)pt/g, function( str ) {
return Math.round(parseFloat(str) * 96 / 72) + "px";
} ) : value;
}
var me = this, autoClearEmptyNode = me.options.autoClearEmptyNode,
EMPTY_TAG = dtd.$empty,
parseHTML = function () {
//干掉 后便变得空格,保留 这样的空格
var RE_PART = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\s\/>]+)\s*((?:(?:"[^"]*")|(?:'[^']*')|[^"'<>])*)\/?>))/g,
RE_ATTR = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g,
EMPTY_ATTR = {checked:1,compact:1,declare:1,defer:1,disabled:1,ismap:1,multiple:1,nohref:1,noresize:1,noshade:1,nowrap:1,readonly:1,selected:1},
CDATA_TAG = {script:1,style: 1},
NEED_PARENT_TAG = {
"li": { "$": 'ul', "ul": 1, "ol": 1 },
"dd": { "$": "dl", "dl": 1 },
"dt": { "$": "dl", "dl": 1 },
"option": { "$": "select", "select": 1 },
"td": { "$": "tr", "tr": 1 },
"th": { "$": "tr", "tr": 1 },
"tr": { "$": "tbody", "tbody": 1, "thead": 1, "tfoot": 1, "table": 1 },
"tbody": { "$": "table", 'table':1,"colgroup": 1 },
"thead": { "$": "table", "table": 1 },
"tfoot": { "$": "table", "table": 1 },
"col": { "$": "colgroup","colgroup":1 }
};
var NEED_CHILD_TAG = {
"table": "td", "tbody": "td", "thead": "td", "tfoot": "td", "tr": "td",
"colgroup": "col",
"ul": "li", "ol": "li",
"dl": "dd",
"select": "option"
};
function parse( html, callbacks ) {
var match,
nextIndex = 0,
tagName,
cdata;
RE_PART.exec( "" );
while ( (match = RE_PART.exec( html )) ) {
var tagIndex = match.index;
if ( tagIndex > nextIndex ) {
var text = html.slice( nextIndex, tagIndex );
if ( cdata ) {
cdata.push( text );
} else {
callbacks.onText( text );
}
}
nextIndex = RE_PART.lastIndex;
if ( (tagName = match[1]) ) {
tagName = tagName.toLowerCase();
if ( cdata && tagName == cdata._tag_name ) {
callbacks.onCDATA( cdata.join( '' ) );
cdata = null;
}
if ( !cdata ) {
callbacks.onTagClose( tagName );
continue;
}
}
if ( cdata ) {
cdata.push( match[0] );
continue;
}
if ( (tagName = match[3]) ) {
if ( /="/.test( tagName ) ) {
continue;
}
tagName = tagName.toLowerCase();
var attrPart = match[4],
attrMatch,
attrMap = {},
selfClosing = attrPart && attrPart.slice( -1 ) == '/';
if ( attrPart ) {
RE_ATTR.exec( "" );
while ( (attrMatch = RE_ATTR.exec( attrPart )) ) {
var attrName = attrMatch[1].toLowerCase(),
attrValue = attrMatch[2] || attrMatch[3] || attrMatch[4] || '';
if ( !attrValue && EMPTY_ATTR[attrName] ) {
attrValue = attrName;
}
if ( attrName == 'style' ) {
if ( ie && version <= 6 ) {
attrValue = attrValue.replace( /(?!;)\s*([\w-]+):/g, function ( m, p1 ) {
return p1.toLowerCase() + ':';
} );
}
}
//没有值的属性不添加
if ( attrValue ) {
attrMap[attrName] = attrValue.replace( /:\s*/g, ':' )
}
}
}
callbacks.onTagOpen( tagName, attrMap, selfClosing );
if ( !cdata && CDATA_TAG[tagName] ) {
cdata = [];
cdata._tag_name = tagName;
}
continue;
}
if ( (tagName = match[2]) ) {
callbacks.onComment( tagName );
}
}
if ( html.length > nextIndex ) {
callbacks.onText( html.slice( nextIndex, html.length ) );
}
}
return function ( html, forceDtd ) {
var fragment = {
type: 'fragment',
parent: null,
children: []
};
var currentNode = fragment;
function addChild( node ) {
node.parent = currentNode;
currentNode.children.push( node );
}
function addElement( element, open ) {
var node = element;
// 遇到结构化标签的时候
if ( NEED_PARENT_TAG[node.tag] ) {
// 考虑这种情况的时候, 结束之前的标签
// e.g. | 12312` |
`4566
while ( NEED_PARENT_TAG[currentNode.tag] && NEED_PARENT_TAG[currentNode.tag][node.tag] ) {
currentNode = currentNode.parent;
}
// 如果前一个标签和这个标签是同一级, 结束之前的标签
// e.g. - 123
-
if ( currentNode.tag == node.tag ) {
currentNode = currentNode.parent;
}
// 向上补齐父标签
while ( NEED_PARENT_TAG[node.tag] ) {
if ( NEED_PARENT_TAG[node.tag][currentNode.tag] ) break;
node = node.parent = {
type: 'element',
tag: NEED_PARENT_TAG[node.tag]['$'],
attributes: {},
children: [node]
};
}
}
if ( forceDtd ) {
// 如果遇到这个标签不能放在前一个标签内部,则结束前一个标签,span单独处理
while ( dtd[node.tag] && !(currentNode.tag == 'span' ? utils.extend( dtd['strong'], {'a':1,'A':1} ) : (dtd[currentNode.tag] || dtd['div']))[node.tag] ) {
if ( tagEnd( currentNode ) ) continue;
if ( !currentNode.parent ) break;
currentNode = currentNode.parent;
}
}
node.parent = currentNode;
currentNode.children.push( node );
if ( open ) {
currentNode = element;
}
if ( element.attributes.style ) {
element.attributes.style = element.attributes.style.toLowerCase();
}
return element;
}
// 结束一个标签的时候,需要判断一下它是否缺少子标签
// e.g.
function tagEnd( node ) {
var needTag;
if ( !node.children.length && (needTag = NEED_CHILD_TAG[node.tag]) ) {
addElement( {
type: 'element',
tag: needTag,
attributes: {},
children: []
}, true );
return true;
}
return false;
}
parse( html, {
onText: function ( text ) {
while ( !(dtd[currentNode.tag] || dtd['div'])['#'] ) {
//节点之间的空白不能当作节点处理
// if(/^[ \t\r\n]+$/.test( text )){
// return;
// }
if ( tagEnd( currentNode ) ) continue;
currentNode = currentNode.parent;
}
//if(/^[ \t\n\r]*/.test(text))
addChild( {
type: 'text',
data: text
} );
},
onComment: function ( text ) {
addChild( {
type: 'comment',
data: text
} );
},
onCDATA: function ( text ) {
while ( !(dtd[currentNode.tag] || dtd['div'])['#'] ) {
if ( tagEnd( currentNode ) ) continue;
currentNode = currentNode.parent;
}
addChild( {
type: 'cdata',
data: text
} );
},
onTagOpen: function ( tag, attrs, closed ) {
closed = closed || EMPTY_TAG[tag] ;
addElement( {
type: 'element',
tag: tag,
attributes: attrs,
closed: closed,
children: []
}, !closed );
},
onTagClose: function ( tag ) {
var node = currentNode;
// 向上找匹配的标签, 这里不考虑dtd的情况是因为tagOpen的时候已经处理过了, 这里不会遇到
while ( node && tag != node.tag ) {
node = node.parent;
}
if ( node ) {
// 关闭中间的标签
for ( var tnode = currentNode; tnode !== node.parent; tnode = tnode.parent ) {
tagEnd( tnode );
}
//去掉空白的inline节点
//分页,锚点保留
//|| dtd.$removeEmptyBlock[node.tag])
// if ( !node.children.length && dtd.$removeEmpty[node.tag] && !node.attributes.anchorname && node.attributes['class'] != 'pagebreak' && node.tag != 'a') {
//
// node.parent.children.pop();
// }
currentNode = node.parent;
} else {
// 如果没有找到开始标签, 则创建新标签
// eg. =>
//针对视屏网站embed会给结束符,这里特殊处理一下
if ( !(dtd.$removeEmpty[tag] || dtd.$removeEmptyBlock[tag] || tag == 'embed') ) {
node = {
type: 'element',
tag: tag,
attributes: {},
children: []
};
addElement( node, true );
tagEnd( node );
currentNode = node.parent;
}
}
}
} );
// 处理这种情况, 只有开始标签没有结束标签的情况, 需要关闭开始标签
// eg.
while ( currentNode !== fragment ) {
tagEnd( currentNode );
currentNode = currentNode.parent;
}
return fragment;
};
}();
var unhtml1 = function () {
var map = { '<': '<', '>': '>', '"': '"', "'": ''' };
function rep( m ) {
return map[m];
}
return function ( str ) {
str = str + '';
return str ? str.replace( /[<>"']/g, rep ) : '';
};
}();
var toHTML = function () {
function printChildren( node, pasteplain ) {
var children = node.children;
var buff = [];
for ( var i = 0,ci; ci = children[i]; i++ ) {
buff.push( toHTML( ci, pasteplain ) );
}
return buff.join( '' );
}
function printAttrs( attrs ) {
var buff = [];
for ( var k in attrs ) {
var value = attrs[k];
if(k == 'style'){
//pt==>px
value = ptToPx(value);
//color rgb ==> hex
if(/rgba?\s*\([^)]*\)/.test(value)){
value = value.replace( /rgba?\s*\(([^)]*)\)/g, function( str ) {
return utils.fixColor('color',str);
} )
}
//过滤掉所有的white-space,在纯文本编辑器里粘贴过来的内容,到chrome中会带有span和white-space属性,导致出现不能折行的情况
//所以在这里去掉这个属性
attrs[k] = utils.optCss(value.replace(/windowtext/g,'#000'))
.replace(/white-space[^;]+;/g,'');
}
buff.push( k + '="' + unhtml1( attrs[k] ) + '"' );
}
return buff.join( ' ' )
}
function printData( node, notTrans ) {
//trace:1399 输入html代码时空格转换成为
//node.data.replace(/ /g,' ') 针对pre中的空格和出现的 把他们在得到的html代码中都转换成为空格,为了在源码模式下显示为空格而不是
return notTrans ? node.data.replace(/ /g,' ') : unhtml1( node.data ).replace(/ /g,' ');
}
//纯文本模式下标签转换
var transHtml = {
'div':'p',
'li':'p',
'tr':'p',
'br':'br',
'p':'p'//trace:1398 碰到p标签自己要加上p,否则transHtml[tag]是undefined
};
function printElement( node, pasteplain ) {
if ( node.type == 'element' && !node.children.length && (dtd.$removeEmpty[node.tag]) && node.tag != 'a' && utils.isEmptyObject(node.attributes) && autoClearEmptyNode) {// 锚点保留
return html;
}
var tag = node.tag;
if ( pasteplain && tag == 'td' ) {
if ( !html ) html = '';
html += printChildren( node, pasteplain ) + ' ';
} else {
var attrs = printAttrs( node.attributes );
var html = '<' + (pasteplain && transHtml[tag] ? transHtml[tag] : tag) + (attrs ? ' ' + attrs : '') + (EMPTY_TAG[tag] ? ' />' : '>');
if ( !EMPTY_TAG[tag] ) {
//trace:1627 ,2070
//p标签为空,将不占位这里占位符不起作用,用 或者br
if( tag == 'p' && !node.children.length){
html += browser.ie ? ' ' : '
';
}
html += printChildren( node, pasteplain );
html += '' + (pasteplain && transHtml[tag] ? transHtml[tag] : tag) + '>';
}
}
return html;
}
return function ( node, pasteplain ) {
if ( node.type == 'fragment' ) {
return printChildren( node, pasteplain );
} else if ( node.type == 'element' ) {
return printElement( node, pasteplain );
} else if ( node.type == 'text' || node.type == 'cdata' ) {
return printData( node, dtd.$notTransContent[node.parent.tag] );
} else if ( node.type == 'comment' ) {
return '';
}
return '';
};
}();
//过滤word
var transformWordHtml = function () {
function isWordDocument( strValue ) {
var re = new RegExp( /(class="?Mso|style="[^"]*\bmso\-|w:WordDocument|[\s\S]*$/, '' )
//remove link break
.replace( /^(\r\n|\n|\r)|(\r\n|\n|\r)$/ig, "" )
//remove entities at the start of contents
.replace( /^\s*( )+/ig, "" )
//remove entities at the end of contents
.replace( /( |
]*>)+\s*$/ig, "" )
// Word comments like conditional comments etc
.replace( //ig, "" )
//转换图片
.replace(/]*>[\s\S]*?.<\/v:shape>/gi,function(str){
try{
var width = str.match(/width:([ \d.]*p[tx])/i)[1],
height = str.match(/height:([ \d.]*p[tx])/i)[1],
src = str.match(/src=\s*"([^"]*)"/i)[1];
return '
'
} catch(e){
return '';
}
})
//去掉多余的属性
.replace( /v:\w+=["']?[^'"]+["']?/g, '' )
// Remove comments, scripts (e.g., msoShowComment), XML tag, VML content, MS Office namespaced tags, and a few other tags
.replace( /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|xml|meta|link|style|\w+:\w+)(?=[\s\/>]))[^>]*>/gi, "" )
//convert word headers to strong
.replace( /]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi, "
$1
" )
//remove lang attribute
.replace( /(lang)\s*=\s*([\'\"]?)[\w-]+\2/ig, "" )
//清除多余的font不能匹配 有可能是空格
.replace( /]*>\s*<\/font>/gi, '' )
//清除多余的class
.replace( /class\s*=\s*["']?(?:(?:MsoTableGrid)|(?:MsoListParagraph)|(?:MsoNormal(Table)?))\s*["']?/gi, '' );
// Examine all styles: delete junk, transform some, and keep the rest
//修复了原有的问题, 比如style='fontsize:"宋体"'原来的匹配失效了
str = str.replace( /(<[a-z][^>]*)\sstyle=(["'])([^\2]*?)\2/gi, function( str, tag, tmp, style ) {
var n = [],
i = 0,
s = style.replace( /^\s+|\s+$/, '' ).replace( /"/gi, "'" ).split( /;\s*/g );
// Examine each style definition within the tag's style attribute
for ( var i = 0; i < s.length; i++ ) {
var v = s[i];
var name, value,
parts = v.split( ":" );
if ( parts.length == 2 ) {
name = parts[0].toLowerCase();
value = parts[1].toLowerCase();
// Translate certain MS Office styles into their CSS equivalents
switch ( name ) {
case "mso-padding-alt":
case "mso-padding-top-alt":
case "mso-padding-right-alt":
case "mso-padding-bottom-alt":
case "mso-padding-left-alt":
case "mso-margin-alt":
case "mso-margin-top-alt":
case "mso-margin-right-alt":
case "mso-margin-bottom-alt":
case "mso-margin-left-alt":
//ie下会出现挤到一起的情况
// case "mso-table-layout-alt":
case "mso-height":
case "mso-width":
case "mso-vertical-align-alt":
//trace:1819 ff下会解析出padding在table上
if(!/ 0 ) {
return tag + ' style="' + n.join( ';' ) + '"';
} else {
return tag;
}
} );
str = str.replace( /([ ]+)<\/span>/ig, function ( m, p ) {
return new Array( p.length + 1 ).join( ' ' ) + '';
} );
return str;
}
return function ( html ) {
//过了word,才能转p->li
first = null;
parentTag = '',liStyle = '',firstTag = '';
if ( isWordDocument( html ) ) {
html = filterPasteWord( html );
}
return html.replace( />[ \t\r\n]*<' );
};
}();
var NODE_NAME_MAP = {
'text': '#text',
'comment': '#comment',
'cdata': '#cdata-section',
'fragment': '#document-fragment'
};
// function _likeLi( node ) {
// var a;
// if ( node && node.tag == 'p' ) {
// //office 2011下有效
// if ( node.attributes['class'] == 'MsoListParagraph' || /mso-list/.test( node.attributes.style ) ) {
// a = 1;
// } else {
// var firstChild = node.children[0];
// if ( firstChild && firstChild.tag == 'span' && /Wingdings/i.test( firstChild.attributes.style ) ) {
// a = 1;
// }
// }
// }
// return a;
// }
//为p==>li 做个标志
var first,
// orderStyle = {
// 'decimal' : /\d+/,
// 'lower-roman': /^m{0,4}(cm|cd|d?c{0,3})(xc|xl|l?x{0,3})(ix|iv|v?i{0,3})$/,
// 'upper-roman': /^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/,
// 'lower-alpha' : /^\(?[a-z]+\)?$/,
// 'upper-alpha': /^\(?[A-Z]+\)?$/
// },
// unorderStyle = { 'disc' : /^[l\u00B7\u2002]/, 'circle' : /^[\u006F\u00D8]/,'square' : /^[\u006E\u25C6]/},
parentTag = '',liStyle = '',firstTag;
//写入编辑器时,调用,进行转换操作
function transNode( node, word_img_flag ) {
var sizeMap = [0, 10, 12, 16, 18, 24, 32, 48],
attr,
indexOf = utils.indexOf;
switch ( node.tag ) {
case 'script':
node.tag = 'div';
node.attributes._ue_div_script = 1;
node.attributes._ue_script_data = node.children[0] ? encodeURIComponent(node.children[0].data) : '';
node.children = [];
break;
case 'img':
//todo base64暂时去掉,后边做远程图片上传后,干掉这个
if(node.attributes.src && /^data:/.test(node.attributes.src)){
return {
type : 'fragment',
children:[]
}
}
if ( node.attributes.src && /^(?:file)/.test( node.attributes.src ) ) {
if ( !/(gif|bmp|png|jpg|jpeg)$/.test( node.attributes.src ) ) {
return {
type : 'fragment',
children:[]
}
}
node.attributes.word_img = node.attributes.src;
node.attributes.src = me.options.UEDITOR_HOME_URL + 'themes/default/images/spacer.gif';
var flag = parseInt(node.attributes.width)<128||parseInt(node.attributes.height)<43;
node.attributes.style="background:url(" + me.options.UEDITOR_HOME_URL +"themes/default/images/"+(flag?"word.gif":"localimage.png")+") no-repeat center center;border:1px solid #ddd";
//node.attributes.style = 'width:395px;height:173px;';
word_img_flag && (word_img_flag.flag = 1);
}
if(browser.ie && browser.version < 7 )
node.attributes.orgSrc = node.attributes.src;
node.attributes.data_ue_src = node.attributes.data_ue_src || node.attributes.src;
break;
case 'li':
var child = node.children[0];
if ( !child || child.type != 'element' || child.tag != 'p' && dtd.p[child.tag] ) {
var tmpPNode = {
type: 'element',
tag: 'p',
attributes: {},
parent : node
};
tmpPNode.children = child ? node.children :[
browser.ie ? {
type:'text',
data:domUtils.fillChar,
parent : tmpPNode
}:
{
type : 'element',
tag : 'br',
attributes:{},
closed: true,
children: [],
parent : tmpPNode
}
];
node.children = [tmpPNode];
}
break;
case 'table':
case 'td':
optStyle( node );
break;
case 'a'://锚点,a==>img
if ( node.attributes['anchorname'] ) {
node.tag = 'img';
node.attributes = {
'class' : 'anchorclass',
'anchorname':node.attributes['name']
};
node.closed = 1;
}
node.attributes.href && (node.attributes.data_ue_src = node.attributes.href);
break;
case 'b':
node.tag = node.name = 'strong';
break;
case 'i':
node.tag = node.name = 'em';
break;
case 'u':
node.tag = node.name = 'span';
node.attributes.style = (node.attributes.style || '') + ';text-decoration:underline;';
break;
case 's':
case 'del':
node.tag = node.name = 'span';
node.attributes.style = (node.attributes.style || '') + ';text-decoration:line-through;';
if ( node.children.length == 1 ) {
child = node.children[0];
if ( child.tag == node.tag ) {
node.attributes.style += ";" + child.attributes.style;
node.children = child.children;
}
}
break;
case 'span':
// if ( /mso-list/.test( node.attributes.style ) ) {
//
//
// //判断了两次就不在判断了
// if ( firstTag != 'end' ) {
//
// var ci = node.children[0],p;
// while ( ci.type == 'element' ) {
// ci = ci.children[0];
// }
// for ( p in unorderStyle ) {
// if ( unorderStyle[p].test( ci.data ) ) {
//
// // ci.data = ci.data.replace(unorderStyle[p],'');
// parentTag = 'ul';
// liStyle = p;
// break;
// }
// }
//
//
// if ( !parentTag ) {
// for ( p in orderStyle ) {
// if ( orderStyle[p].test( ci.data.replace( /\.$/, '' ) ) ) {
// // ci.data = ci.data.replace(orderStyle[p],'');
// parentTag = 'ol';
// liStyle = p;
// break;
// }
// }
// }
// if ( firstTag ) {
// if ( ci.data == firstTag ) {
// if ( parentTag != 'ul' ) {
// liStyle = '';
// }
// parentTag = 'ul'
// } else {
// if ( parentTag != 'ol' ) {
// liStyle = '';
// }
// parentTag = 'ol'
// }
// firstTag = 'end'
// } else {
// firstTag = ci.data
// }
// if ( parentTag ) {
// var tmpNode = node;
// while ( tmpNode && tmpNode.tag != 'ul' && tmpNode.tag != 'ol' ) {
// tmpNode = tmpNode.parent;
// }
// if(tmpNode ){
// tmpNode.tag = parentTag;
// tmpNode.attributes.style = 'list-style-type:' + liStyle;
// }
//
//
//
// }
//
// }
//
// node = {
// type : 'fragment',
// children : []
// };
// break;
//
//
// }
var style = node.attributes.style;
if ( style ) {
if ( !node.attributes.style || browser.webkit && style == "white-space:nowrap;") {
delete node.attributes.style;
}
}
//针对ff3.6span的样式不能正确继承的修复
if(browser.gecko && browser.version <= 10902 && node.parent){
var parent = node.parent;
if(parent.tag == 'span' && parent.attributes && parent.attributes.style){
node.attributes.style = parent.attributes.style + ';' + node.attributes.style;
}
}
if ( utils.isEmptyObject( node.attributes ) && autoClearEmptyNode) {
node.type = 'fragment'
}
break;
case 'font':
node.tag = node.name = 'span';
attr = node.attributes;
node.attributes = {
'style': (attr.size ? 'font-size:' + (sizeMap[attr.size] || 12) + 'px' : '')
+ ';' + (attr.color ? 'color:'+ attr.color : '')
+ ';' + (attr.face ? 'font-family:'+ attr.face : '')
+ ';' + (attr.style||'')
};
while(node.parent.tag == node.tag && node.parent.children.length == 1){
node.attributes.style && (node.parent.attributes.style ? (node.parent.attributes.style += ";" + node.attributes.style) : (node.parent.attributes.style = node.attributes.style));
node.parent.children = node.children;
node = node.parent;
}
break;
case 'p':
if ( node.attributes.align ) {
node.attributes.style = (node.attributes.style || '') + ';text-align:' +
node.attributes.align + ';';
delete node.attributes.align;
}
// if ( _likeLi( node ) ) {
//
// if ( !first ) {
//
// var ulNode = {
// type: 'element',
// tag: 'ul',
// attributes: {},
// children: []
// },
// index = indexOf( node.parent.children, node );
// node.parent.children[index] = ulNode;
// ulNode.parent = node.parent;
// ulNode.children[0] = node;
// node.parent = ulNode;
//
// while ( 1 ) {
// node = ulNode.parent.children[index + 1];
// if ( _likeLi( node ) ) {
// ulNode.children[ulNode.children.length] = node;
// node.parent = ulNode;
// ulNode.parent.children.splice( index + 1, 1 );
//
// } else {
// break;
// }
// }
//
// return ulNode;
// }
// node.tag = node.name = 'li';
// //为chrome能找到标号做的处理
// if ( browser.webkit ) {
// var span = node.children[0];
//
// while ( span && span.type == 'element' ) {
// span = span.children[0]
// }
// span && (span.parent.attributes.style = (span.parent.attributes.style || '') + ';mso-list:10');
// }
//
//
// delete node.attributes['class'];
// delete node.attributes.style;
//
//
// }
}
return node;
}
function optStyle( node ) {
if ( ie && node.attributes.style ) {
var style = node.attributes.style;
node.attributes.style = style.replace(/;\s*/g,';');
node.attributes.style = node.attributes.style.replace( /^\s*|\s*$/, '' )
}
}
//getContent调用转换
function transOutNode( node ) {
switch ( node.tag ) {
case 'div' :
if(node.attributes._ue_div_script){
node.tag = 'script';
node.children = [{type:'cdata',data:decodeURIComponent(node.attributes._ue_script_data)||'',parent:node}];
delete node.attributes._ue_div_script;
delete node.attributes._ue_script_data;
break;
}
case 'table':
!node.attributes.style && delete node.attributes.style;
if ( ie && node.attributes.style ) {
optStyle( node );
}
if(node.attributes['class'] == 'noBorderTable'){
delete node.attributes['class'];
}
break;
case 'td':
case 'th':
if ( /display\s*:\s*none/i.test( node.attributes.style ) ) {
return {
type: 'fragment',
children: []
};
}
if ( ie && !node.children.length ) {
var txtNode = {
type: 'text',
data:domUtils.fillChar,
parent : node
};
node.children[0] = txtNode;
}
if ( ie && node.attributes.style ) {
optStyle( node );
}
if(node.attributes['class'] == 'selectTdClass'){
delete node.attributes['class']
}
break;
case 'img'://锚点,img==>a
if ( node.attributes.anchorname ) {
node.tag = 'a';
node.attributes = {
name : node.attributes.anchorname,
anchorname : 1
};
node.closed = null;
}else{
if(node.attributes.data_ue_src){
node.attributes.src = node.attributes.data_ue_src;
delete node.attributes.data_ue_src;
}
}
break;
case 'a':
if(node.attributes.data_ue_src){
node.attributes.href = node.attributes.data_ue_src;
delete node.attributes.data_ue_src;
}
}
return node;
}
function childrenAccept( node, visit, ctx ) {
if ( !node.children || !node.children.length ) {
return node;
}
var children = node.children;
for ( var i = 0; i < children.length; i++ ) {
var newNode = visit( children[i], ctx );
if ( newNode.type == 'fragment' ) {
var args = [i, 1];
args.push.apply( args, newNode.children );
children.splice.apply( children, args );
//节点为空的就干掉,不然后边的补全操作会添加多余的节点
if ( !children.length ) {
node = {
type: 'fragment',
children: []
}
}
i --;
} else {
children[i] = newNode;
}
}
return node;
}
function Serialize( rules ) {
this.rules = rules;
}
Serialize.prototype = {
// NOTE: selector目前只支持tagName
rules: null,
// NOTE: node必须是fragment
filter: function ( node, rules, modify ) {
rules = rules || this.rules;
var whiteList = rules && rules.whiteList;
var blackList = rules && rules.blackList;
function visitNode( node, parent ) {
node.name = node.type == 'element' ?
node.tag : NODE_NAME_MAP[node.type];
if ( parent == null ) {
return childrenAccept( node, visitNode, node );
}
if ( blackList && blackList[node.name] ) {
modify && (modify.flag = 1);
return {
type: 'fragment',
children: []
};
}
if ( whiteList ) {
if ( node.type == 'element' ) {
if ( parent.type == 'fragment' ? whiteList[node.name] : whiteList[node.name] && whiteList[parent.name][node.name] ) {
var props;
if ( (props = whiteList[node.name].$) ) {
var oldAttrs = node.attributes;
var newAttrs = {};
for ( var k in props ) {
if ( oldAttrs[k] ) {
newAttrs[k] = oldAttrs[k];
}
}
node.attributes = newAttrs;
}
} else {
modify && (modify.flag = 1);
node.type = 'fragment';
// NOTE: 这里算是一个hack
node.name = parent.name;
}
} else {
// NOTE: 文本默认允许
}
}
if ( blackList || whiteList ) {
childrenAccept( node, visitNode, node );
}
return node;
}
return visitNode( node, null );
},
transformInput: function ( node, word_img_flag ) {
function visitNode( node ) {
node = transNode( node, word_img_flag );
// if ( node.tag == 'ol' || node.tag == 'ul' ) {
// first = 1;
// }
node = childrenAccept( node, visitNode, node );
// if ( node.tag == 'ol' || node.tag == 'ul' ) {
// first = 0;
// parentTag = '',liStyle = '',firstTag = '';
// }
if ( me.options.pageBreakTag && node.type == 'text' && node.data.replace( /\s/g, '' ) == me.options.pageBreakTag ) {
node.type = 'element';
node.name = node.tag = 'hr';
delete node.data;
node.attributes = {
'class' : 'pagebreak',
noshade:"noshade",
size:"5",
'unselectable' : 'on',
'style' : 'moz-user-select:none;-khtml-user-select: none;'
};
node.children = [];
}
//去掉多余的空格和换行
if(node.type == 'text' && !dtd.$notTransContent[node.parent.tag]){
node.data = node.data.replace(/[\r\t\n]*/g,'')//.replace(/[ ]*$/g,'')
}
return node;
}
return visitNode( node );
},
transformOutput: function ( node ) {
function visitNode( node ) {
if ( node.tag == 'hr' && node.attributes['class'] == 'pagebreak' ) {
delete node.tag;
node.type = 'text';
node.data = me.options.pageBreakTag;
delete node.children;
}
node = transOutNode( node );
if ( node.tag == 'ol' || node.tag == 'ul' ) {
first = 1;
}
node = childrenAccept( node, visitNode, node );
if ( node.tag == 'ol' || node.tag == 'ul' ) {
first = 0;
}
return node;
}
return visitNode( node );
},
toHTML: toHTML,
parseHTML: parseHTML,
word: transformWordHtml
};
me.serialize = new Serialize( me.options.serialize || {});
UE.serialize = new Serialize( {} );
};
///import core
///import plugins/inserthtml.js
///commands 视频
///commandsName InsertVideo
///commandsTitle 插入视频
///commandsDialog dialogs\video\video.html
UE.plugins['video'] = function (){
var me =this,
div;
/**
* 创建插入视频字符窜
* @param url 视频地址
* @param width 视频宽度
* @param height 视频高度
* @param align 视频对齐
* @param toEmbed 是否以图片代替显示
* @param addParagraph 是否需要添加P 标签
*/
function creatInsertStr(url,width,height,align,toEmbed,addParagraph){
return !toEmbed ?
(addParagraph? (''): '') +
'
' +
(addParagraph?'
':'')
:
'