]/.test(html)) {
return UE.htmlparser(html).children[0]
} else {
return new uNode({
type: 'element',
children: [],
tagName: html
})
}
};
uNode.createText = function (data, noTrans) {
return new UE.uNode({
type: 'text',
'data': noTrans ? data : utils.unhtml(data || '')
})
};
function nodeToHtml(node, arr, formatter, current) {
switch (node.type) {
case 'root':
for (var i = 0, ci; ci = node.children[i++];) {
//插入新行
if (formatter && ci.type == 'element' && !dtd.$inlineWithA[ci.tagName] && i > 1) {
insertLine(arr, current, true);
insertIndent(arr, current)
}
nodeToHtml(ci, arr, formatter, current)
}
break;
case 'text':
isText(node, arr);
break;
case 'element':
isElement(node, arr, formatter, current);
break;
case 'comment':
isComment(node, arr, formatter);
}
return arr;
}
function isText(node, arr) {
if (node.parentNode.tagName == 'pre') {
//源码模式下输入html标签,不能做转换处理,直接输出
arr.push(node.data)
} else {
arr.push(notTransTagName[node.parentNode.tagName] ? utils.html(node.data) : node.data.replace(/[ ]{2}/g, ' '))
}
}
function isElement(node, arr, formatter, current) {
var attrhtml = '';
if (node.attrs) {
attrhtml = [];
var attrs = node.attrs;
for (var a in attrs) {
//这里就针对
//'
//这里边的\"做转换,要不用innerHTML直接被截断了,属性src
//有可能做的不够
attrhtml.push(a + (attrs[a] !== undefined ? '="' + (notTransAttrs[a] ? utils.html(attrs[a]).replace(/["]/g, function (a) {
return '"'
}) : utils.unhtml(attrs[a])) + '"' : ''))
}
attrhtml = attrhtml.join(' ');
}
arr.push('<' + node.tagName +
(attrhtml ? ' ' + attrhtml : '') +
(dtd.$empty[node.tagName] ? '\/' : '') + '>'
);
//插入新行
if (formatter && !dtd.$inlineWithA[node.tagName] && node.tagName != 'pre') {
if (node.children && node.children.length) {
current = insertLine(arr, current, true);
insertIndent(arr, current)
}
}
if (node.children && node.children.length) {
for (var i = 0, ci; ci = node.children[i++];) {
if (formatter && ci.type == 'element' && !dtd.$inlineWithA[ci.tagName] && i > 1) {
insertLine(arr, current);
insertIndent(arr, current)
}
nodeToHtml(ci, arr, formatter, current)
}
}
if (!dtd.$empty[node.tagName]) {
if (formatter && !dtd.$inlineWithA[node.tagName] && node.tagName != 'pre') {
if (node.children && node.children.length) {
current = insertLine(arr, current);
insertIndent(arr, current)
}
}
arr.push('<\/' + node.tagName + '>');
}
}
function isComment(node, arr) {
arr.push('');
}
function getNodeById(root, id) {
var node;
if (root.type == 'element' && root.getAttr('id') == id) {
return root;
}
if (root.children && root.children.length) {
for (var i = 0, ci; ci = root.children[i++];) {
if (node = getNodeById(ci, id)) {
return node;
}
}
}
}
function getNodesByTagName(node, tagName, arr) {
if (node.type == 'element' && node.tagName == tagName) {
arr.push(node);
}
if (node.children && node.children.length) {
for (var i = 0, ci; ci = node.children[i++];) {
getNodesByTagName(ci, tagName, arr)
}
}
}
function nodeTraversal(root, fn) {
if (root.children && root.children.length) {
for (var i = 0, ci; ci = root.children[i];) {
nodeTraversal(ci, fn);
//ci被替换的情况,这里就不再走 fn了
if (ci.parentNode) {
if (ci.children && ci.children.length) {
fn(ci)
}
if (ci.parentNode) i++
}
}
} else {
fn(root)
}
}
uNode.prototype = {
/**
* 当前节点对象,转换成html文本
* @method toHtml
* @return { String } 返回转换后的html字符串
* @example
* ```javascript
* node.toHtml();
* ```
*/
/**
* 当前节点对象,转换成html文本
* @method toHtml
* @param { Boolean } formatter 是否格式化返回值
* @return { String } 返回转换后的html字符串
* @example
* ```javascript
* node.toHtml( true );
* ```
*/
toHtml: function (formatter) {
var arr = [];
nodeToHtml(this, arr, formatter, 0);
return arr.join('')
},
/**
* 获取节点的html内容
* @method innerHTML
* @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点
* @return { String } 返回节点的html内容
* @example
* ```javascript
* var htmlstr = node.innerHTML();
* ```
*/
/**
* 设置节点的html内容
* @method innerHTML
* @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点
* @param { String } htmlstr 传入要设置的html内容
* @return { UE.uNode } 返回节点本身
* @example
* ```javascript
* node.innerHTML('text ');
* ```
*/
innerHTML: function (htmlstr) {
if (this.type != 'element' || dtd.$empty[this.tagName]) {
return this;
}
if (utils.isString(htmlstr)) {
if (this.children) {
for (var i = 0, ci; ci = this.children[i++];) {
ci.parentNode = null;
}
}
this.children = [];
var tmpRoot = UE.htmlparser(htmlstr);
for (var i = 0, ci; ci = tmpRoot.children[i++];) {
this.children.push(ci);
ci.parentNode = this;
}
return this;
} else {
var tmpRoot = new UE.uNode({
type: 'root',
children: this.children
});
return tmpRoot.toHtml();
}
},
/**
* 获取节点的纯文本内容
* @method innerText
* @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点
* @return { String } 返回节点的存文本内容
* @example
* ```javascript
* var textStr = node.innerText();
* ```
*/
/**
* 设置节点的纯文本内容
* @method innerText
* @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点
* @param { String } textStr 传入要设置的文本内容
* @return { UE.uNode } 返回节点本身
* @example
* ```javascript
* node.innerText('text ');
* ```
*/
innerText: function (textStr, noTrans) {
if (this.type != 'element' || dtd.$empty[this.tagName]) {
return this;
}
if (textStr) {
if (this.children) {
for (var i = 0, ci; ci = this.children[i++];) {
ci.parentNode = null;
}
}
this.children = [];
this.appendChild(uNode.createText(textStr, noTrans));
return this;
} else {
return this.toHtml().replace(/<[^>]+>/g, '');
}
},
/**
* 获取当前对象的data属性
* @method getData
* @return { Object } 若节点的type值是elemenet,返回空字符串,否则返回节点的data属性
* @example
* ```javascript
* node.getData();
* ```
*/
getData: function () {
if (this.type == 'element')
return '';
return this.data
},
/**
* 获取当前节点下的第一个子节点
* @method firstChild
* @return { UE.uNode } 返回第一个子节点
* @example
* ```javascript
* node.firstChild(); //返回第一个子节点
* ```
*/
firstChild: function () {
// if (this.type != 'element' || dtd.$empty[this.tagName]) {
// return this;
// }
return this.children ? this.children[0] : null;
},
/**
* 获取当前节点下的最后一个子节点
* @method lastChild
* @return { UE.uNode } 返回最后一个子节点
* @example
* ```javascript
* node.lastChild(); //返回最后一个子节点
* ```
*/
lastChild: function () {
// if (this.type != 'element' || dtd.$empty[this.tagName] ) {
// return this;
// }
return this.children ? this.children[this.children.length - 1] : null;
},
/**
* 获取和当前节点有相同父亲节点的前一个节点
* @method previousSibling
* @return { UE.uNode } 返回前一个节点
* @example
* ```javascript
* node.children[2].previousSibling(); //返回子节点node.children[1]
* ```
*/
previousSibling: function () {
var parent = this.parentNode;
for (var i = 0, ci; ci = parent.children[i]; i++) {
if (ci === this) {
return i == 0 ? null : parent.children[i - 1];
}
}
},
/**
* 获取和当前节点有相同父亲节点的后一个节点
* @method nextSibling
* @return { UE.uNode } 返回后一个节点,找不到返回null
* @example
* ```javascript
* node.children[2].nextSibling(); //如果有,返回子节点node.children[3]
* ```
*/
nextSibling: function () {
var parent = this.parentNode;
for (var i = 0, ci; ci = parent.children[i++];) {
if (ci === this) {
return parent.children[i];
}
}
},
/**
* 用新的节点替换当前节点
* @method replaceChild
* @param { UE.uNode } target 要替换成该节点参数
* @param { UE.uNode } source 要被替换掉的节点
* @return { UE.uNode } 返回替换之后的节点对象
* @example
* ```javascript
* node.replaceChild(newNode, childNode); //用newNode替换childNode,childNode是node的子节点
* ```
*/
replaceChild: function (target, source) {
if (this.children) {
if (target.parentNode) {
target.parentNode.removeChild(target);
}
for (var i = 0, ci; ci = this.children[i]; i++) {
if (ci === source) {
this.children.splice(i, 1, target);
source.parentNode = null;
target.parentNode = this;
return target;
}
}
}
},
/**
* 在节点的子节点列表最后位置插入一个节点
* @method appendChild
* @param { UE.uNode } node 要插入的节点
* @return { UE.uNode } 返回刚插入的子节点
* @example
* ```javascript
* node.appendChild( newNode ); //在node内插入子节点newNode
* ```
*/
appendChild: function (node) {
if (this.type == 'root' || (this.type == 'element' && !dtd.$empty[this.tagName])) {
if (!this.children) {
this.children = []
}
if (node.parentNode) {
node.parentNode.removeChild(node);
}
for (var i = 0, ci; ci = this.children[i]; i++) {
if (ci === node) {
this.children.splice(i, 1);
break;
}
}
this.children.push(node);
node.parentNode = this;
return node;
}
},
/**
* 在传入节点的前面插入一个节点
* @method insertBefore
* @param { UE.uNode } target 要插入的节点
* @param { UE.uNode } source 在该参数节点前面插入
* @return { UE.uNode } 返回刚插入的子节点
* @example
* ```javascript
* node.parentNode.insertBefore(newNode, node); //在node节点后面插入newNode
* ```
*/
insertBefore: function (target, source) {
if (this.children) {
if (target.parentNode) {
target.parentNode.removeChild(target);
}
for (var i = 0, ci; ci = this.children[i]; i++) {
if (ci === source) {
this.children.splice(i, 0, target);
target.parentNode = this;
return target;
}
}
}
},
/**
* 在传入节点的后面插入一个节点
* @method insertAfter
* @param { UE.uNode } target 要插入的节点
* @param { UE.uNode } source 在该参数节点后面插入
* @return { UE.uNode } 返回刚插入的子节点
* @example
* ```javascript
* node.parentNode.insertAfter(newNode, node); //在node节点后面插入newNode
* ```
*/
insertAfter: function (target, source) {
if (this.children) {
if (target.parentNode) {
target.parentNode.removeChild(target);
}
for (var i = 0, ci; ci = this.children[i]; i++) {
if (ci === source) {
this.children.splice(i + 1, 0, target);
target.parentNode = this;
return target;
}
}
}
},
/**
* 从当前节点的子节点列表中,移除节点
* @method removeChild
* @param { UE.uNode } node 要移除的节点引用
* @param { Boolean } keepChildren 是否保留移除节点的子节点,若传入true,自动把移除节点的子节点插入到移除的位置
* @return { * } 返回刚移除的子节点
* @example
* ```javascript
* node.removeChild(childNode,true); //在node的子节点列表中移除child节点,并且吧child的子节点插入到移除的位置
* ```
*/
removeChild: function (node, keepChildren) {
if (this.children) {
for (var i = 0, ci; ci = this.children[i]; i++) {
if (ci === node) {
this.children.splice(i, 1);
ci.parentNode = null;
if (keepChildren && ci.children && ci.children.length) {
for (var j = 0, cj; cj = ci.children[j]; j++) {
this.children.splice(i + j, 0, cj);
cj.parentNode = this;
}
}
return ci;
}
}
}
},
/**
* 获取当前节点所代表的元素属性,即获取attrs对象下的属性值
* @method getAttr
* @param { String } attrName 要获取的属性名称
* @return { * } 返回attrs对象下的属性值
* @example
* ```javascript
* node.getAttr('title');
* ```
*/
getAttr: function (attrName) {
return this.attrs && this.attrs[attrName.toLowerCase()]
},
/**
* 设置当前节点所代表的元素属性,即设置attrs对象下的属性值
* @method setAttr
* @param { String } attrName 要设置的属性名称
* @param { * } attrVal 要设置的属性值,类型视设置的属性而定
* @return { * } 返回attrs对象下的属性值
* @example
* ```javascript
* node.setAttr('title','标题');
* ```
*/
setAttr: function (attrName, attrVal) {
if (!attrName) {
delete this.attrs;
return;
}
if (!this.attrs) {
this.attrs = {};
}
if (utils.isObject(attrName)) {
for (var a in attrName) {
if (!attrName[a]) {
delete this.attrs[a]
} else {
this.attrs[a.toLowerCase()] = attrName[a];
}
}
} else {
if (!attrVal) {
delete this.attrs[attrName]
} else {
this.attrs[attrName.toLowerCase()] = attrVal;
}
}
},
/**
* 获取当前节点在父节点下的位置索引
* @method getIndex
* @return { Number } 返回索引数值,如果没有父节点,返回-1
* @example
* ```javascript
* node.getIndex();
* ```
*/
getIndex: function () {
var parent = this.parentNode;
for (var i = 0, ci; ci = parent.children[i]; i++) {
if (ci === this) {
return i;
}
}
return -1;
},
/**
* 在当前节点下,根据id查找节点
* @method getNodeById
* @param { String } id 要查找的id
* @return { UE.uNode } 返回找到的节点
* @example
* ```javascript
* node.getNodeById('textId');
* ```
*/
getNodeById: function (id) {
var node;
if (this.children && this.children.length) {
for (var i = 0, ci; ci = this.children[i++];) {
if (node = getNodeById(ci, id)) {
return node;
}
}
}
},
/**
* 在当前节点下,根据元素名称查找节点列表
* @method getNodesByTagName
* @param { String } tagNames 要查找的元素名称
* @return { Array } 返回找到的节点列表
* @example
* ```javascript
* node.getNodesByTagName('span');
* ```
*/
getNodesByTagName: function (tagNames) {
tagNames = utils.trim(tagNames).replace(/[ ]{2,}/g, ' ').split(' ');
var arr = [], me = this;
utils.each(tagNames, function (tagName) {
if (me.children && me.children.length) {
for (var i = 0, ci; ci = me.children[i++];) {
getNodesByTagName(ci, tagName, arr)
}
}
});
return arr;
},
/**
* 根据样式名称,获取节点的样式值
* @method getStyle
* @param { String } name 要获取的样式名称
* @return { String } 返回样式值
* @example
* ```javascript
* node.getStyle('font-size');
* ```
*/
getStyle: function (name) {
var cssStyle = this.getAttr('style');
if (!cssStyle) {
return ''
}
var reg = new RegExp('(^|;)\\s*' + name + ':([^;]+)', 'i');
var match = cssStyle.match(reg);
if (match && match[0]) {
return match[2]
}
return '';
},
/**
* 给节点设置样式
* @method setStyle
* @param { String } name 要设置的的样式名称
* @param { String } val 要设置的的样值
* @example
* ```javascript
* node.setStyle('font-size', '12px');
* ```
*/
setStyle: function (name, val) {
function exec(name, val) {
var reg = new RegExp('(^|;)\\s*' + name + ':([^;]+;?)', 'gi');
cssStyle = cssStyle.replace(reg, '$1');
if (val) {
cssStyle = name + ':' + utils.unhtml(val) + ';' + cssStyle
}
}
var cssStyle = this.getAttr('style');
if (!cssStyle) {
cssStyle = '';
}
if (utils.isObject(name)) {
for (var a in name) {
exec(a, name[a])
}
} else {
exec(name, val)
}
this.setAttr('style', utils.trim(cssStyle))
},
/**
* 传入一个函数,递归遍历当前节点下的所有节点
* @method traversal
* @param { Function } fn 遍历到节点的时,传入节点作为参数,运行此函数
* @example
* ```javascript
* traversal(node, function(){
* console.log(node.type);
* });
* ```
*/
traversal: function (fn) {
if (this.children && this.children.length) {
nodeTraversal(this, fn);
}
return this;
}
}
})();
// core/htmlparser.js
/**
* html字符串转换成uNode节点
* @file
* @module UE
* @since 1.2.6.1
*/
/**
* UEditor公用空间,UEditor所有的功能都挂载在该空间下
* @unfile
* @module UE
*/
/**
* html字符串转换成uNode节点的静态方法
* @method htmlparser
* @param { String } htmlstr 要转换的html代码
* @param { Boolean } ignoreBlank 若设置为true,转换的时候忽略\n\r\t等空白字符
* @return { uNode } 给定的html片段转换形成的uNode对象
* @example
* ```javascript
* var root = UE.htmlparser('htmlparser
', true);
* ```
*/
var htmlparser = UE.htmlparser = function (htmlstr, ignoreBlank) {
//todo 原来的方式 [^"'<>\/] 有\/就不能配对上 这样的标签了
//先去掉了,加上的原因忘了,这里先记录
var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\s\/<>]+)\s*((?:(?:"[^"]*")|(?:'[^']*')|[^"'<>])*)\/?>))/g,
re_attr = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g;
//ie下取得的html可能会有\n存在,要去掉,在处理replace(/[\t\r\n]*/g,'');代码高量的\n不能去除
var allowEmptyTags = {
b: 1, code: 1, i: 1, u: 1, strike: 1, s: 1, tt: 1, strong: 1, q: 1, samp: 1, em: 1, span: 1,
sub: 1, img: 1, sup: 1, font: 1, big: 1, small: 1, iframe: 1, a: 1, br: 1, pre: 1
};
htmlstr = htmlstr.replace(new RegExp(domUtils.fillChar, 'g'), '');
if (!ignoreBlank) {
htmlstr = htmlstr.replace(new RegExp('[\\r\\t\\n' + (ignoreBlank ? '' : ' ') + ']*<\/?(\\w+)\\s*(?:[^>]*)>[\\r\\t\\n' + (ignoreBlank ? '' : ' ') + ']*', 'g'), function (a, b) {
//br暂时单独处理
if (b && allowEmptyTags[b.toLowerCase()]) {
return a.replace(/(^[\n\r]+)|([\n\r]+$)/g, '');
}
return a.replace(new RegExp('^[\\r\\n' + (ignoreBlank ? '' : ' ') + ']+'), '').replace(new RegExp('[\\r\\n' + (ignoreBlank ? '' : ' ') + ']+$'), '');
});
}
var notTransAttrs = {
'href': 1,
'src': 1
};
var uNode = UE.uNode,
needParentNode = {
'td': 'tr',
'tr': ['tbody', 'thead', 'tfoot'],
'tbody': 'table',
'th': 'tr',
'thead': 'table',
'tfoot': 'table',
'caption': 'table',
'li': ['ul', 'ol'],
'dt': 'dl',
'dd': 'dl',
'option': 'select'
},
needChild = {
'ol': 'li',
'ul': 'li'
};
function text(parent, data) {
if (needChild[parent.tagName]) {
var tmpNode = uNode.createElement(needChild[parent.tagName]);
parent.appendChild(tmpNode);
tmpNode.appendChild(uNode.createText(data));
parent = tmpNode;
} else {
parent.appendChild(uNode.createText(data));
}
}
function element(parent, tagName, htmlattr) {
var needParentTag;
if (needParentTag = needParentNode[tagName]) {
var tmpParent = parent, hasParent;
while (tmpParent.type != 'root') {
if (utils.isArray(needParentTag) ? utils.indexOf(needParentTag, tmpParent.tagName) != -1 : needParentTag == tmpParent.tagName) {
parent = tmpParent;
hasParent = true;
break;
}
tmpParent = tmpParent.parentNode;
}
if (!hasParent) {
parent = element(parent, utils.isArray(needParentTag) ? needParentTag[0] : needParentTag)
}
}
//按dtd处理嵌套
// if(parent.type != 'root' && !dtd[parent.tagName][tagName])
// parent = parent.parentNode;
var elm = new uNode({
parentNode: parent,
type: 'element',
tagName: tagName.toLowerCase(),
//是自闭合的处理一下
children: dtd.$empty[tagName] ? null : []
});
//如果属性存在,处理属性
if (htmlattr) {
var attrs = {}, match;
while (match = re_attr.exec(htmlattr)) {
attrs[match[1].toLowerCase()] = notTransAttrs[match[1].toLowerCase()] ? (match[2] || match[3] || match[4]) : utils.unhtml(match[2] || match[3] || match[4])
}
elm.attrs = attrs;
}
//trace:3970
// //如果parent下不能放elm
// if(dtd.$inline[parent.tagName] && dtd.$block[elm.tagName] && !dtd[parent.tagName][elm.tagName]){
// parent = parent.parentNode;
// elm.parentNode = parent;
// }
parent.children.push(elm);
//如果是自闭合节点返回父亲节点
return dtd.$empty[tagName] ? parent : elm
}
function comment(parent, data) {
parent.children.push(new uNode({
type: 'comment',
data: data,
parentNode: parent
}));
}
var match, currentIndex = 0, nextIndex = 0;
//设置根节点
var root = new uNode({
type: 'root',
children: []
});
var currentParent = root;
while (match = re_tag.exec(htmlstr)) {
currentIndex = match.index;
try {
if (currentIndex > nextIndex) {
//text node
text(currentParent, htmlstr.slice(nextIndex, currentIndex));
}
if (match[3]) {
if (dtd.$cdata[currentParent.tagName]) {
text(currentParent, match[0]);
} else {
//start tag
currentParent = element(currentParent, match[3].toLowerCase(), match[4]);
}
} else if (match[1]) {
if (currentParent.type != 'root') {
if (dtd.$cdata[currentParent.tagName] && !dtd.$cdata[match[1]]) {
text(currentParent, match[0]);
} else {
var tmpParent = currentParent;
while (currentParent.type == 'element' && currentParent.tagName != match[1].toLowerCase()) {
currentParent = currentParent.parentNode;
if (currentParent.type == 'root') {
currentParent = tmpParent;
throw 'break'
}
}
//end tag
currentParent = currentParent.parentNode;
}
}
} else if (match[2]) {
//comment
comment(currentParent, match[2])
}
} catch (e) { }
nextIndex = re_tag.lastIndex;
}
//如果结束是文本,就有可能丢掉,所以这里手动判断一下
//例如 sdfsdfsdf sdfsdfsdfsdf
if (nextIndex < htmlstr.length) {
text(currentParent, htmlstr.slice(nextIndex));
}
return root;
};
// core/filternode.js
/**
* UE过滤节点的静态方法
* @file
*/
/**
* UEditor公用空间,UEditor所有的功能都挂载在该空间下
* @module UE
*/
/**
* 根据传入节点和过滤规则过滤相应节点
* @module UE
* @since 1.2.6.1
* @method filterNode
* @param { Object } root 指定root节点
* @param { Object } rules 过滤规则json对象
* @example
* ```javascript
* UE.filterNode(root,editor.options.filterRules);
* ```
*/
var filterNode = UE.filterNode = function () {
function filterNode(node, rules) {
switch (node.type) {
case 'text':
break;
case 'element':
var val;
if (val = rules[node.tagName]) {
if (val === '-') {
node.parentNode.removeChild(node)
} else if (utils.isFunction(val)) {
var parentNode = node.parentNode,
index = node.getIndex();
val(node);
if (node.parentNode) {
if (node.children) {
for (var i = 0, ci; ci = node.children[i];) {
filterNode(ci, rules);
if (ci.parentNode) {
i++;
}
}
}
} else {
for (var i = index, ci; ci = parentNode.children[i];) {
filterNode(ci, rules);
if (ci.parentNode) {
i++;
}
}
}
} else {
var attrs = val['$'];
if (attrs && node.attrs) {
var tmpAttrs = {}, tmpVal;
for (var a in attrs) {
tmpVal = node.getAttr(a);
//todo 只先对style单独处理
if (a == 'style' && utils.isArray(attrs[a])) {
var tmpCssStyle = [];
utils.each(attrs[a], function (v) {
var tmp;
if (tmp = node.getStyle(v)) {
tmpCssStyle.push(v + ':' + tmp);
}
});
tmpVal = tmpCssStyle.join(';')
}
if (tmpVal) {
tmpAttrs[a] = tmpVal;
}
}
node.attrs = tmpAttrs;
}
if (node.children) {
for (var i = 0, ci; ci = node.children[i];) {
filterNode(ci, rules);
if (ci.parentNode) {
i++;
}
}
}
}
} else {
//如果不在名单里扣出子节点并删除该节点,cdata除外
if (dtd.$cdata[node.tagName]) {
node.parentNode.removeChild(node)
} else {
var parentNode = node.parentNode,
index = node.getIndex();
node.parentNode.removeChild(node, true);
for (var i = index, ci; ci = parentNode.children[i];) {
filterNode(ci, rules);
if (ci.parentNode) {
i++;
}
}
}
}
break;
case 'comment':
node.parentNode.removeChild(node)
}
}
return function (root, rules) {
if (utils.isEmptyObject(rules)) {
return root;
}
var val;
if (val = rules['-']) {
utils.each(val.split(' '), function (k) {
rules[k] = '-'
})
}
for (var i = 0, ci; ci = root.children[i];) {
filterNode(ci, rules);
if (ci.parentNode) {
i++;
}
}
return root;
}
}();
// core/plugin.js
/**
* Created with JetBrains PhpStorm.
* User: campaign
* Date: 10/8/13
* Time: 6:15 PM
* To change this template use File | Settings | File Templates.
*/
UE.plugin = function () {
var _plugins = {};
return {
register: function (pluginName, fn, oldOptionName, afterDisabled) {
if (oldOptionName && utils.isFunction(oldOptionName)) {
afterDisabled = oldOptionName;
oldOptionName = null
}
_plugins[pluginName] = {
optionName: oldOptionName || pluginName,
execFn: fn,
//当插件被禁用时执行
afterDisabled: afterDisabled
}
},
load: function (editor) {
utils.each(_plugins, function (plugin) {
var _export = plugin.execFn.call(editor);
if (editor.options[plugin.optionName] !== false) {
if (_export) {
//后边需要再做扩展
utils.each(_export, function (v, k) {
switch (k.toLowerCase()) {
case 'shortcutkey':
editor.addshortcutkey(v);
break;
case 'bindevents':
utils.each(v, function (fn, eventName) {
editor.addListener(eventName, fn);
});
break;
case 'bindmultievents':
utils.each(utils.isArray(v) ? v : [v], function (event) {
var types = utils.trim(event.type).split(/\s+/);
utils.each(types, function (eventName) {
editor.addListener(eventName, event.handler);
});
});
break;
case 'commands':
utils.each(v, function (execFn, execName) {
editor.commands[execName] = execFn
});
break;
case 'outputrule':
editor.addOutputRule(v);
break;
case 'inputrule':
editor.addInputRule(v);
break;
case 'defaultoptions':
editor.setOpt(v)
}
})
}
} else if (plugin.afterDisabled) {
plugin.afterDisabled.call(editor)
}
});
//向下兼容
utils.each(UE.plugins, function (plugin) {
plugin.call(editor);
});
},
run: function (pluginName, editor) {
var plugin = _plugins[pluginName];
if (plugin) {
plugin.exeFn.call(editor)
}
}
}
}();
// core/keymap.js
var keymap = UE.keymap = {
'Backspace': 8,
'Tab': 9,
'Enter': 13,
'Shift': 16,
'Control': 17,
'Alt': 18,
'CapsLock': 20,
'Esc': 27,
'Spacebar': 32,
'PageUp': 33,
'PageDown': 34,
'End': 35,
'Home': 36,
'Left': 37,
'Up': 38,
'Right': 39,
'Down': 40,
'Insert': 45,
'Del': 46,
'NumLock': 144,
'Cmd': 91,
'=': 187,
'-': 189,
"b": 66,
'i': 73,
//回退
'z': 90,
'y': 89,
//粘贴
'v': 86,
'x': 88,
's': 83,
'n': 78
};
// core/localstorage.js
//存储媒介封装
var LocalStorage = UE.LocalStorage = (function () {
var storage = window.localStorage || getUserData() || null,
LOCAL_FILE = 'localStorage';
return {
saveLocalData: function (key, data) {
if (storage && data) {
storage.setItem(key, data);
return true;
}
return false;
},
getLocalData: function (key) {
if (storage) {
return storage.getItem(key);
}
return null;
},
removeItem: function (key) {
storage && storage.removeItem(key);
}
};
function getUserData() {
var container = document.createElement("div");
container.style.display = "none";
if (!container.addBehavior) {
return null;
}
container.addBehavior("#default#userdata");
return {
getItem: function (key) {
var result = null;
try {
document.body.appendChild(container);
container.load(LOCAL_FILE);
result = container.getAttribute(key);
document.body.removeChild(container);
} catch (e) {
}
return result;
},
setItem: function (key, value) {
document.body.appendChild(container);
container.setAttribute(key, value);
container.save(LOCAL_FILE);
document.body.removeChild(container);
},
//// 暂时没有用到
//clear: function () {
//
// var expiresTime = new Date();
// expiresTime.setFullYear(expiresTime.getFullYear() - 1);
// document.body.appendChild(container);
// container.expires = expiresTime.toUTCString();
// container.save(LOCAL_FILE);
// document.body.removeChild(container);
//
//},
removeItem: function (key) {
document.body.appendChild(container);
container.removeAttribute(key);
container.save(LOCAL_FILE);
document.body.removeChild(container);
}
};
}
})();
(function () {
var ROOTKEY = 'ueditor_preference';
UE.Editor.prototype.setPreferences = function (key, value) {
var obj = {};
if (utils.isString(key)) {
obj[key] = value;
} else {
obj = key;
}
var data = LocalStorage.getLocalData(ROOTKEY);
if (data && (data = utils.str2json(data))) {
utils.extend(data, obj);
} else {
data = obj;
}
data && LocalStorage.saveLocalData(ROOTKEY, utils.json2str(data));
};
UE.Editor.prototype.getPreferences = function (key) {
var data = LocalStorage.getLocalData(ROOTKEY);
if (data && (data = utils.str2json(data))) {
return key ? data[key] : data
}
return null;
};
UE.Editor.prototype.removePreferences = function (key) {
var data = LocalStorage.getLocalData(ROOTKEY);
if (data && (data = utils.str2json(data))) {
data[key] = undefined;
delete data[key]
}
data && LocalStorage.saveLocalData(ROOTKEY, utils.json2str(data));
};
})();
// plugins/defaultfilter.js
///import core
///plugin 编辑器默认的过滤转换机制
UE.plugins['defaultfilter'] = function () {
var me = this;
me.setOpt({
'allowDivTransToP': true,
'disabledTableInTable': true
});
//默认的过滤处理
//进入编辑器的内容处理
me.addInputRule(function (root) {
var allowDivTransToP = this.options.allowDivTransToP;
var val;
function tdParent(node) {
while (node && node.type == 'element') {
if (node.tagName == 'td') {
return true;
}
node = node.parentNode;
}
return false;
}
//进行默认的处理
root.traversal(function (node) {
if (node.type == 'element') {
if (!dtd.$cdata[node.tagName] && me.options.autoClearEmptyNode && dtd.$inline[node.tagName] && !dtd.$empty[node.tagName] && (!node.attrs || utils.isEmptyObject(node.attrs))) {
if (!node.firstChild()) node.parentNode.removeChild(node);
else if (node.tagName == 'span' && (!node.attrs || utils.isEmptyObject(node.attrs))) {
node.parentNode.removeChild(node, true)
}
return;
}
switch (node.tagName) {
//case 'style':
case 'script':
node.setAttr({
cdata_tag: node.tagName,
cdata_data: (node.innerHTML() || ''),
'_ue_custom_node_': 'true'
});
node.tagName = 'div';
node.innerHTML('');
break;
case 'a':
if (val = node.getAttr('href')) {
node.setAttr('_href', val)
}
break;
case 'img':
//todo base64暂时去掉,后边做远程图片上传后,干掉这个
if (val = node.getAttr('src')) {
if (/^data:/.test(val)) {
node.parentNode.removeChild(node);
break;
}
}
node.setAttr('_src', node.getAttr('src'));
break;
case 'span':
if (browser.webkit && (val = node.getStyle('white-space'))) {
if (/nowrap|normal/.test(val)) {
node.setStyle('white-space', '');
if (me.options.autoClearEmptyNode && utils.isEmptyObject(node.attrs)) {
node.parentNode.removeChild(node, true)
}
}
}
val = node.getAttr('id');
if (val && /^_baidu_bookmark_/i.test(val)) {
node.parentNode.removeChild(node)
}
break;
case 'p':
if (val = node.getAttr('align')) {
node.setAttr('align');
node.setStyle('text-align', val)
}
//trace:3431
// var cssStyle = node.getAttr('style');
// if (cssStyle) {
// cssStyle = cssStyle.replace(/(margin|padding)[^;]+/g, '');
// node.setAttr('style', cssStyle)
//
// }
//p标签不允许嵌套
utils.each(node.children, function (n) {
if (n.type == 'element' && n.tagName == 'p') {
var next = n.nextSibling();
node.parentNode.insertAfter(n, node);
var last = n;
while (next) {
var tmp = next.nextSibling();
node.parentNode.insertAfter(next, last);
last = next;
next = tmp;
}
return false;
}
});
if (!node.firstChild()) {
node.innerHTML(browser.ie ? ' ' : ' ')
}
break;
case 'div':
if (node.getAttr('cdata_tag')) {
break;
}
//针对代码这里不处理插入代码的div
val = node.getAttr('class');
if (val && /^line number\d+/.test(val)) {
break;
}
if (!allowDivTransToP) {
break;
}
var tmpNode, p = UE.uNode.createElement('p');
while (tmpNode = node.firstChild()) {
if (tmpNode.type == 'text' || !UE.dom.dtd.$block[tmpNode.tagName]) {
p.appendChild(tmpNode);
} else {
if (p.firstChild()) {
node.parentNode.insertBefore(p, node);
p = UE.uNode.createElement('p');
} else {
node.parentNode.insertBefore(tmpNode, node);
}
}
}
if (p.firstChild()) {
node.parentNode.insertBefore(p, node);
}
node.parentNode.removeChild(node);
break;
case 'dl':
node.tagName = 'ul';
break;
case 'dt':
case 'dd':
node.tagName = 'li';
break;
case 'li':
var className = node.getAttr('class');
if (!className || !/list\-/.test(className)) {
node.setAttr()
}
var tmpNodes = node.getNodesByTagName('ol ul');
UE.utils.each(tmpNodes, function (n) {
node.parentNode.insertAfter(n, node);
});
break;
case 'td':
case 'th':
case 'caption':
if (!node.children || !node.children.length) {
node.appendChild(browser.ie11below ? UE.uNode.createText(' ') : UE.uNode.createElement('br'))
}
break;
case 'table':
if (me.options.disabledTableInTable && tdParent(node)) {
node.parentNode.insertBefore(UE.uNode.createText(node.innerText()), node);
node.parentNode.removeChild(node)
}
}
}
// if(node.type == 'comment'){
// node.parentNode.removeChild(node);
// }
})
});
//从编辑器出去的内容处理
me.addOutputRule(function (root) {
var val;
root.traversal(function (node) {
if (node.type == 'element') {
if (me.options.autoClearEmptyNode && dtd.$inline[node.tagName] && !dtd.$empty[node.tagName] && (!node.attrs || utils.isEmptyObject(node.attrs))) {
if (!node.firstChild()) node.parentNode.removeChild(node);
else if (node.tagName == 'span' && (!node.attrs || utils.isEmptyObject(node.attrs))) {
node.parentNode.removeChild(node, true)
}
return;
}
switch (node.tagName) {
case 'div':
if (val = node.getAttr('cdata_tag')) {
node.tagName = val;
node.appendChild(UE.uNode.createText(node.getAttr('cdata_data')));
node.setAttr({ cdata_tag: '', cdata_data: '', '_ue_custom_node_': '' });
}
break;
case 'a':
if (val = node.getAttr('_href')) {
node.setAttr({
'href': utils.html(val),
'_href': ''
})
}
break;
break;
case 'span':
val = node.getAttr('id');
if (val && /^_baidu_bookmark_/i.test(val)) {
node.parentNode.removeChild(node)
}
break;
case 'img':
if (val = node.getAttr('_src')) {
node.setAttr({
'src': node.getAttr('_src'),
'_src': ''
})
}
}
}
})
});
};
// plugins/inserthtml.js
/**
* 插入html字符串插件
* @file
* @since 1.2.6.1
*/
/**
* 插入html代码
* @command inserthtml
* @method execCommand
* @param { String } cmd 命令字符串
* @param { String } html 插入的html字符串
* @remaind 插入的标签内容是在当前的选区位置上插入,如果当前是闭合状态,那直接插入内容, 如果当前是选中状态,将先清除当前选中内容后,再做插入
* @warning 注意:该命令会对当前选区的位置,对插入的内容进行过滤转换处理。 过滤的规则遵循html语意化的原则。
* @example
* ```javascript
* //xxx[BB]xxx 当前选区为非闭合选区,选中BB这两个文本
* //执行命令,插入CC
* //插入后的效果 xxxCC xxx
* //xx|xxx
当前选区为闭合状态
* //插入CC
* //结果 xx
CC
xxx
* //xxxx
|xxx 当前选区在两个p标签之间
* //插入 xxxx
* //结果 xxxx
xxxx
xxx
* ```
*/
UE.commands['inserthtml'] = {
execCommand: function (command, html, notNeedFilter) {
var me = this,
range,
div;
if (!html) {
return;
}
if (me.fireEvent('beforeinserthtml', html) === true) {
return;
}
range = me.selection.getRange();
div = range.document.createElement('div');
div.style.display = 'inline';
if (!notNeedFilter) {
var root = UE.htmlparser(html);
//如果给了过滤规则就先进行过滤
if (me.options.filterRules) {
UE.filterNode(root, me.options.filterRules);
}
//执行默认的处理
me.filterInputRule(root);
html = root.toHtml()
}
div.innerHTML = utils.trim(html);
if (!range.collapsed) {
var tmpNode = range.startContainer;
if (domUtils.isFillChar(tmpNode)) {
range.setStartBefore(tmpNode)
}
tmpNode = range.endContainer;
if (domUtils.isFillChar(tmpNode)) {
range.setEndAfter(tmpNode)
}
range.txtToElmBoundary();
//结束边界可能放到了br的前边,要把br包含进来
// x[xxx]
if (range.endContainer && range.endContainer.nodeType == 1) {
tmpNode = range.endContainer.childNodes[range.endOffset];
if (tmpNode && domUtils.isBr(tmpNode)) {
range.setEndAfter(tmpNode);
}
}
if (range.startOffset == 0) {
tmpNode = range.startContainer;
if (domUtils.isBoundaryNode(tmpNode, 'firstChild')) {
tmpNode = range.endContainer;
if (range.endOffset == (tmpNode.nodeType == 3 ? tmpNode.nodeValue.length : tmpNode.childNodes.length) && domUtils.isBoundaryNode(tmpNode, 'lastChild')) {
me.body.innerHTML = '' + (browser.ie ? '' : ' ') + '
';
range.setStart(me.body.firstChild, 0).collapse(true)
}
}
}
!range.collapsed && range.deleteContents();
if (range.startContainer.nodeType == 1) {
var child = range.startContainer.childNodes[range.startOffset], pre;
if (child && domUtils.isBlockElm(child) && (pre = child.previousSibling) && domUtils.isBlockElm(pre)) {
range.setEnd(pre, pre.childNodes.length).collapse();
while (child.firstChild) {
pre.appendChild(child.firstChild);
}
domUtils.remove(child);
}
}
}
var child, parent, pre, tmp, hadBreak = 0, nextNode;
//如果当前位置选中了fillchar要干掉,要不会产生空行
if (range.inFillChar()) {
child = range.startContainer;
if (domUtils.isFillChar(child)) {
range.setStartBefore(child).collapse(true);
domUtils.remove(child);
} else if (domUtils.isFillChar(child, true)) {
child.nodeValue = child.nodeValue.replace(fillCharReg, '');
range.startOffset--;
range.collapsed && range.collapse(true)
}
}
//列表单独处理
var li = domUtils.findParentByTagName(range.startContainer, 'li', true);
if (li) {
var next, last;
while (child = div.firstChild) {
//针对hr单独处理一下先
while (child && (child.nodeType == 3 || !domUtils.isBlockElm(child) || child.tagName == 'HR')) {
next = child.nextSibling;
range.insertNode(child).collapse();
last = child;
child = next;
}
if (child) {
if (/^(ol|ul)$/i.test(child.tagName)) {
while (child.firstChild) {
last = child.firstChild;
domUtils.insertAfter(li, child.firstChild);
li = li.nextSibling;
}
domUtils.remove(child)
} else {
var tmpLi;
next = child.nextSibling;
tmpLi = me.document.createElement('li');
domUtils.insertAfter(li, tmpLi);
tmpLi.appendChild(child);
last = child;
child = next;
li = tmpLi;
}
}
}
li = domUtils.findParentByTagName(range.startContainer, 'li', true);
if (domUtils.isEmptyBlock(li)) {
domUtils.remove(li)
}
if (last) {
range.setStartAfter(last).collapse(true).select(true)
}
} else {
while (child = div.firstChild) {
if (hadBreak) {
var p = me.document.createElement('p');
while (child && (child.nodeType == 3 || !dtd.$block[child.tagName])) {
nextNode = child.nextSibling;
p.appendChild(child);
child = nextNode;
}
if (p.firstChild) {
child = p
}
}
range.insertNode(child);
nextNode = child.nextSibling;
if (!hadBreak && child.nodeType == domUtils.NODE_ELEMENT && domUtils.isBlockElm(child)) {
parent = domUtils.findParent(child, function (node) { return domUtils.isBlockElm(node); });
if (parent && parent.tagName.toLowerCase() != 'body' && !(dtd[parent.tagName][child.nodeName] && child.parentNode === parent)) {
if (!dtd[parent.tagName][child.nodeName]) {
pre = parent;
} else {
tmp = child.parentNode;
while (tmp !== parent) {
pre = tmp;
tmp = tmp.parentNode;
}
}
domUtils.breakParent(child, pre || tmp);
//去掉break后前一个多余的节点 |<[p> ==>
|
var pre = child.previousSibling;
domUtils.trimWhiteTextNode(pre);
if (!pre.childNodes.length) {
domUtils.remove(pre);
}
//trace:2012,在非ie的情况,切开后剩下的节点有可能不能点入光标添加br占位
if (!browser.ie &&
(next = child.nextSibling) &&
domUtils.isBlockElm(next) &&
next.lastChild &&
!domUtils.isBr(next.lastChild)) {
next.appendChild(me.document.createElement('br'));
}
hadBreak = 1;
}
}
var next = child.nextSibling;
if (!div.firstChild && next && domUtils.isBlockElm(next)) {
range.setStart(next, 0).collapse(true);
break;
}
range.setEndAfter(child).collapse();
}
child = range.startContainer;
if (nextNode && domUtils.isBr(nextNode)) {
domUtils.remove(nextNode)
}
//用chrome可能有空白展位符
if (domUtils.isBlockElm(child) && domUtils.isEmptyNode(child)) {
if (nextNode = child.nextSibling) {
domUtils.remove(child);
if (nextNode.nodeType == 1 && dtd.$block[nextNode.tagName]) {
range.setStart(nextNode, 0).collapse(true).shrinkBoundary()
}
} else {
try {
child.innerHTML = browser.ie ? domUtils.fillChar : ' ';
} catch (e) {
range.setStartBefore(child);
domUtils.remove(child)
}
}
}
//加上true因为在删除表情等时会删两次,第一次是删的fillData
try {
range.select(true);
} catch (e) { }
}
setTimeout(function () {
range = me.selection.getRange();
range.scrollToView(me.autoHeightEnabled, me.autoHeightEnabled ? domUtils.getXY(me.iframe).y : 0);
me.fireEvent('afterinserthtml', html);
}, 200);
}
};
// plugins/autotypeset.js
/**
* 自动排版
* @file
* @since 1.2.6.1
*/
/**
* 对当前编辑器的内容执行自动排版, 排版的行为根据config配置文件里的“autotypeset”选项进行控制。
* @command autotypeset
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'autotypeset' );
* ```
*/
UE.plugins['autotypeset'] = function () {
this.setOpt({
'autotypeset': {
mergeEmptyline: true, //合并空行
removeClass: true, //去掉冗余的class
removeEmptyline: false, //去掉空行
textAlign: "left", //段落的排版方式,可以是 left,right,center,justify 去掉这个属性表示不执行排版
imageBlockLine: 'center', //图片的浮动方式,独占一行剧中,左右浮动,默认: center,left,right,none 去掉这个属性表示不执行排版
pasteFilter: false, //根据规则过滤没事粘贴进来的内容
clearFontSize: false, //去掉所有的内嵌字号,使用编辑器默认的字号
clearFontFamily: false, //去掉所有的内嵌字体,使用编辑器默认的字体
removeEmptyNode: false, // 去掉空节点
//可以去掉的标签
removeTagNames: utils.extend({ div: 1 }, dtd.$removeEmpty),
indent: false, // 行首缩进
indentValue: '2em', //行首缩进的大小
bdc2sb: false,
tobdc: false
}
});
var me = this,
opt = me.options.autotypeset,
remainClass = {
'selectTdClass': 1,
'pagebreak': 1,
'anchorclass': 1
},
remainTag = {
'li': 1
},
tags = {
div: 1,
p: 1,
//trace:2183 这些也认为是行
blockquote: 1, center: 1, h1: 1, h2: 1, h3: 1, h4: 1, h5: 1, h6: 1,
span: 1
},
highlightCont;
//升级了版本,但配置项目里没有autotypeset
if (!opt) {
return;
}
readLocalOpts();
function isLine(node, notEmpty) {
if (!node || node.nodeType == 3)
return 0;
if (domUtils.isBr(node))
return 1;
if (node && node.parentNode && tags[node.tagName.toLowerCase()]) {
if (highlightCont && highlightCont.contains(node)
||
node.getAttribute('pagebreak')
) {
return 0;
}
return notEmpty ? !domUtils.isEmptyBlock(node) : domUtils.isEmptyBlock(node, new RegExp('[\\s' + domUtils.fillChar
+ ']', 'g'));
}
}
function removeNotAttributeSpan(node) {
if (!node.style.cssText) {
domUtils.removeAttributes(node, ['style']);
if (node.tagName.toLowerCase() == 'span' && domUtils.hasNoAttributes(node)) {
domUtils.remove(node, true);
}
}
}
function autotype(type, html) {
var me = this, cont;
if (html) {
if (!opt.pasteFilter) {
return;
}
cont = me.document.createElement('div');
cont.innerHTML = html.html;
} else {
cont = me.document.body;
}
var nodes = domUtils.getElementsByTagName(cont, '*');
// 行首缩进,段落方向,段间距,段内间距
for (var i = 0, ci; ci = nodes[i++];) {
if (me.fireEvent('excludeNodeinautotype', ci) === true) {
continue;
}
//font-size
if (opt.clearFontSize && ci.style.fontSize) {
domUtils.removeStyle(ci, 'font-size');
removeNotAttributeSpan(ci);
}
//font-family
if (opt.clearFontFamily && ci.style.fontFamily) {
domUtils.removeStyle(ci, 'font-family');
removeNotAttributeSpan(ci);
}
if (isLine(ci)) {
//合并空行
if (opt.mergeEmptyline) {
var next = ci.nextSibling, tmpNode, isBr = domUtils.isBr(ci);
while (isLine(next)) {
tmpNode = next;
next = tmpNode.nextSibling;
if (isBr && (!next || next && !domUtils.isBr(next))) {
break;
}
domUtils.remove(tmpNode);
}
}
//去掉空行,保留占位的空行
if (opt.removeEmptyline && domUtils.inDoc(ci, cont) && !remainTag[ci.parentNode.tagName.toLowerCase()]) {
if (domUtils.isBr(ci)) {
next = ci.nextSibling;
if (next && !domUtils.isBr(next)) {
continue;
}
}
domUtils.remove(ci);
continue;
}
}
if (isLine(ci, true) && ci.tagName != 'SPAN') {
if (opt.indent) {
ci.style.textIndent = opt.indentValue;
}
if (opt.textAlign) {
ci.style.textAlign = opt.textAlign;
}
// if(opt.lineHeight)
// ci.style.lineHeight = opt.lineHeight + 'cm';
}
//去掉class,保留的class不去掉
if (opt.removeClass && ci.className && !remainClass[ci.className.toLowerCase()]) {
if (highlightCont && highlightCont.contains(ci)) {
continue;
}
domUtils.removeAttributes(ci, ['class']);
}
//表情不处理
if (opt.imageBlockLine && ci.tagName.toLowerCase() == 'img' && !ci.getAttribute('emotion')) {
if (html) {
var img = ci;
switch (opt.imageBlockLine) {
case 'left':
case 'right':
case 'none':
var pN = img.parentNode, tmpNode, pre, next;
while (dtd.$inline[pN.tagName] || pN.tagName == 'A') {
pN = pN.parentNode;
}
tmpNode = pN;
if (tmpNode.tagName == 'P' && domUtils.getStyle(tmpNode, 'text-align') == 'center') {
if (!domUtils.isBody(tmpNode) && domUtils.getChildCount(tmpNode, function (node) { return !domUtils.isBr(node) && !domUtils.isWhitespace(node) }) == 1) {
pre = tmpNode.previousSibling;
next = tmpNode.nextSibling;
if (pre && next && pre.nodeType == 1 && next.nodeType == 1 && pre.tagName == next.tagName && domUtils.isBlockElm(pre)) {
pre.appendChild(tmpNode.firstChild);
while (next.firstChild) {
pre.appendChild(next.firstChild);
}
domUtils.remove(tmpNode);
domUtils.remove(next);
} else {
domUtils.setStyle(tmpNode, 'text-align', '');
}
}
}
domUtils.setStyle(img, 'float', opt.imageBlockLine);
break;
case 'center':
if (me.queryCommandValue('imagefloat') != 'center') {
pN = img.parentNode;
domUtils.setStyle(img, 'float', 'none');
tmpNode = img;
while (pN && domUtils.getChildCount(pN, function (node) { return !domUtils.isBr(node) && !domUtils.isWhitespace(node) }) == 1
&& (dtd.$inline[pN.tagName] || pN.tagName == 'A')) {
tmpNode = pN;
pN = pN.parentNode;
}
var pNode = me.document.createElement('p');
domUtils.setAttributes(pNode, {
style: 'text-align:center'
});
tmpNode.parentNode.insertBefore(pNode, tmpNode);
pNode.appendChild(tmpNode);
domUtils.setStyle(tmpNode, 'float', '');
}
}
} else {
var range = me.selection.getRange();
range.selectNode(ci).select();
me.execCommand('imagefloat', opt.imageBlockLine);
}
}
//去掉冗余的标签
if (opt.removeEmptyNode) {
if (opt.removeTagNames[ci.tagName.toLowerCase()] && domUtils.hasNoAttributes(ci) && domUtils.isEmptyBlock(ci)) {
domUtils.remove(ci);
}
}
}
if (opt.tobdc) {
var root = UE.htmlparser(cont.innerHTML);
root.traversal(function (node) {
if (node.type == 'text') {
node.data = ToDBC(node.data)
}
});
cont.innerHTML = root.toHtml()
}
if (opt.bdc2sb) {
var root = UE.htmlparser(cont.innerHTML);
root.traversal(function (node) {
if (node.type == 'text') {
node.data = DBC2SB(node.data)
}
});
cont.innerHTML = root.toHtml()
}
if (html) {
html.html = cont.innerHTML;
}
}
if (opt.pasteFilter) {
me.addListener('beforepaste', autotype);
}
function DBC2SB(str) {
var result = '';
for (var i = 0; i < str.length; i++) {
var code = str.charCodeAt(i); //获取当前字符的unicode编码
if (code >= 65281 && code <= 65373)//在这个unicode编码范围中的是所有的英文字母已经各种字符
{
result += String.fromCharCode(str.charCodeAt(i) - 65248); //把全角字符的unicode编码转换为对应半角字符的unicode码
} else if (code == 12288)//空格
{
result += String.fromCharCode(str.charCodeAt(i) - 12288 + 32);
} else {
result += str.charAt(i);
}
}
return result;
}
function ToDBC(txtstring) {
txtstring = utils.html(txtstring);
var tmp = "";
var mark = "";/*用于判断,如果是html尖括里的标记,则不进行全角的转换*/
for (var i = 0; i < txtstring.length; i++) {
if (txtstring.charCodeAt(i) == 32) {
tmp = tmp + String.fromCharCode(12288);
}
else if (txtstring.charCodeAt(i) < 127) {
tmp = tmp + String.fromCharCode(txtstring.charCodeAt(i) + 65248);
}
else {
tmp += txtstring.charAt(i);
}
}
return tmp;
}
function readLocalOpts() {
var cookieOpt = me.getPreferences('autotypeset');
utils.extend(me.options.autotypeset, cookieOpt);
}
me.commands['autotypeset'] = {
execCommand: function () {
me.removeListener('beforepaste', autotype);
if (opt.pasteFilter) {
me.addListener('beforepaste', autotype);
}
autotype.call(me)
}
};
};
// plugins/autosubmit.js
/**
* 快捷键提交
* @file
* @since 1.2.6.1
*/
/**
* 提交表单
* @command autosubmit
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'autosubmit' );
* ```
*/
UE.plugin.register('autosubmit', function () {
return {
shortcutkey: {
"autosubmit": "ctrl+13" //手动提交
},
commands: {
'autosubmit': {
execCommand: function () {
var me = this,
form = domUtils.findParentByTagName(me.iframe, "form", false);
if (form) {
if (me.fireEvent("beforesubmit") === false) {
return;
}
me.sync();
form.submit();
}
}
}
}
}
});
// plugins/background.js
/**
* 背景插件,为UEditor提供设置背景功能
* @file
* @since 1.2.6.1
*/
UE.plugin.register('background', function () {
var me = this,
cssRuleId = 'editor_background',
isSetColored,
reg = new RegExp('body[\\s]*\\{(.+)\\}', 'i');
function stringToObj(str) {
var obj = {}, styles = str.split(';');
utils.each(styles, function (v) {
var index = v.indexOf(':'),
key = utils.trim(v.substr(0, index)).toLowerCase();
key && (obj[key] = utils.trim(v.substr(index + 1) || ''));
});
return obj;
}
function setBackground(obj) {
if (obj) {
var styles = [];
for (var name in obj) {
if (obj.hasOwnProperty(name)) {
styles.push(name + ":" + obj[name] + '; ');
}
}
utils.cssRule(cssRuleId, styles.length ? ('body{' + styles.join("") + '}') : '', me.document);
} else {
utils.cssRule(cssRuleId, '', me.document)
}
}
//重写editor.hasContent方法
var orgFn = me.hasContents;
me.hasContents = function () {
if (me.queryCommandValue('background')) {
return true
}
return orgFn.apply(me, arguments);
};
return {
bindEvents: {
'getAllHtml': function (type, headHtml) {
var body = this.body,
su = domUtils.getComputedStyle(body, "background-image"),
url = "";
if (su.indexOf(me.options.imagePath) > 0) {
url = su.substring(su.indexOf(me.options.imagePath), su.length - 1).replace(/"|\(|\)/ig, "");
} else {
url = su != "none" ? su.replace(/url\("?|"?\)/ig, "") : "";
}
var html = ' ';
headHtml.push(html);
},
'aftersetcontent': function () {
if (isSetColored == false) setBackground();
}
},
inputRule: function (root) {
isSetColored = false;
utils.each(root.getNodesByTagName('p'), function (p) {
var styles = p.getAttr('data-background');
if (styles) {
isSetColored = true;
setBackground(stringToObj(styles));
p.parentNode.removeChild(p);
}
})
},
outputRule: function (root) {
var me = this,
styles = (utils.cssRule(cssRuleId, me.document) || '').replace(/[\n\r]+/g, '').match(reg);
if (styles) {
root.appendChild(UE.uNode.createElement('
'));
}
},
commands: {
'background': {
execCommand: function (cmd, obj) {
setBackground(obj);
},
queryCommandValue: function () {
var me = this,
styles = (utils.cssRule(cssRuleId, me.document) || '').replace(/[\n\r]+/g, '').match(reg);
return styles ? stringToObj(styles[1]) : null;
},
notNeedUndo: true
}
}
}
});
// plugins/image.js
/**
* 图片插入、排版插件
* @file
* @since 1.2.6.1
*/
/**
* 图片对齐方式
* @command imagefloat
* @method execCommand
* @remind 值center为独占一行居中
* @param { String } cmd 命令字符串
* @param { String } align 对齐方式,可传left、right、none、center
* @remaind center表示图片独占一行
* @example
* ```javascript
* editor.execCommand( 'imagefloat', 'center' );
* ```
*/
/**
* 如果选区所在位置是图片区域
* @command imagefloat
* @method queryCommandValue
* @param { String } cmd 命令字符串
* @return { String } 返回图片对齐方式
* @example
* ```javascript
* editor.queryCommandValue( 'imagefloat' );
* ```
*/
UE.commands['imagefloat'] = {
execCommand: function (cmd, align) {
var me = this,
range = me.selection.getRange();
if (!range.collapsed) {
var img = range.getClosedNode();
if (img && img.tagName == 'IMG') {
switch (align) {
case 'left':
case 'right':
case 'none':
var pN = img.parentNode, tmpNode, pre, next;
while (dtd.$inline[pN.tagName] || pN.tagName == 'A') {
pN = pN.parentNode;
}
tmpNode = pN;
if (tmpNode.tagName == 'P' && domUtils.getStyle(tmpNode, 'text-align') == 'center') {
if (!domUtils.isBody(tmpNode) && domUtils.getChildCount(tmpNode, function (node) {
return !domUtils.isBr(node) && !domUtils.isWhitespace(node);
}) == 1) {
pre = tmpNode.previousSibling;
next = tmpNode.nextSibling;
if (pre && next && pre.nodeType == 1 && next.nodeType == 1 && pre.tagName == next.tagName && domUtils.isBlockElm(pre)) {
pre.appendChild(tmpNode.firstChild);
while (next.firstChild) {
pre.appendChild(next.firstChild);
}
domUtils.remove(tmpNode);
domUtils.remove(next);
} else {
domUtils.setStyle(tmpNode, 'text-align', '');
}
}
range.selectNode(img).select();
}
domUtils.setStyle(img, 'float', align == 'none' ? '' : align);
if (align == 'none') {
domUtils.removeAttributes(img, 'align');
}
break;
case 'center':
if (me.queryCommandValue('imagefloat') != 'center') {
pN = img.parentNode;
domUtils.setStyle(img, 'float', '');
domUtils.removeAttributes(img, 'align');
tmpNode = img;
while (pN && domUtils.getChildCount(pN, function (node) {
return !domUtils.isBr(node) && !domUtils.isWhitespace(node);
}) == 1
&& (dtd.$inline[pN.tagName] || pN.tagName == 'A')) {
tmpNode = pN;
pN = pN.parentNode;
}
range.setStartBefore(tmpNode).setCursor(false);
pN = me.document.createElement('div');
pN.appendChild(tmpNode);
domUtils.setStyle(tmpNode, 'float', '');
me.execCommand('insertHtml', '' + pN.innerHTML + '
');
tmpNode = me.document.getElementById('_img_parent_tmp');
tmpNode.removeAttribute('id');
tmpNode = tmpNode.firstChild;
range.selectNode(tmpNode).select();
//去掉后边多余的元素
next = tmpNode.parentNode.nextSibling;
if (next && domUtils.isEmptyNode(next)) {
domUtils.remove(next);
}
}
break;
}
}
}
},
queryCommandValue: function () {
var range = this.selection.getRange(),
startNode, floatStyle;
if (range.collapsed) {
return 'none';
}
startNode = range.getClosedNode();
if (startNode && startNode.nodeType == 1 && startNode.tagName == 'IMG') {
floatStyle = domUtils.getComputedStyle(startNode, 'float') || startNode.getAttribute('align');
if (floatStyle == 'none') {
floatStyle = domUtils.getComputedStyle(startNode.parentNode, 'text-align') == 'center' ? 'center' : floatStyle;
}
return {
left: 1,
right: 1,
center: 1
}[floatStyle] ? floatStyle : 'none';
}
return 'none';
},
queryCommandState: function () {
var range = this.selection.getRange(),
startNode;
if (range.collapsed) return -1;
startNode = range.getClosedNode();
if (startNode && startNode.nodeType == 1 && startNode.tagName == 'IMG') {
return 0;
}
return -1;
}
};
/**
* 插入图片
* @command insertimage
* @method execCommand
* @param { String } cmd 命令字符串
* @param { Object } opt 属性键值对,这些属性都将被复制到当前插入图片
* @remind 该命令第二个参数可接受一个图片配置项对象的数组,可以插入多张图片,
* 此时数组的每一个元素都是一个Object类型的图片属性集合。
* @example
* ```javascript
* editor.execCommand( 'insertimage', {
* src:'a/b/c.jpg',
* width:'100',
* height:'100'
* } );
* ```
* @example
* ```javascript
* editor.execCommand( 'insertimage', [{
* src:'a/b/c.jpg',
* width:'100',
* height:'100'
* },{
* src:'a/b/d.jpg',
* width:'100',
* height:'100'
* }] );
* ```
*/
UE.commands['insertimage'] = {
execCommand: function (cmd, opt) {
opt = utils.isArray(opt) ? opt : [opt];
if (!opt.length) {
return;
}
var me = this,
range = me.selection.getRange(),
img = range.getClosedNode();
if (me.fireEvent('beforeinsertimage', opt) === true) {
return;
}
function unhtmlData(imgCi) {
utils.each('width,height,border,hspace,vspace'.split(','), function (item) {
if (imgCi[item]) {
imgCi[item] = parseInt(imgCi[item], 10) || 0;
}
});
utils.each('src,_src'.split(','), function (item) {
if (imgCi[item]) {
imgCi[item] = utils.unhtmlForUrl(imgCi[item]);
}
});
utils.each('title,alt'.split(','), function (item) {
if (imgCi[item]) {
imgCi[item] = utils.unhtml(imgCi[item]);
}
});
}
if (img && /img/i.test(img.tagName) && (img.className != "edui-faked-video" || img.className.indexOf("edui-upload-video") != -1) && !img.getAttribute("word_img")) {
var first = opt.shift();
var floatStyle = first['floatStyle'];
delete first['floatStyle'];
//// img.style.border = (first.border||0) +"px solid #000";
//// img.style.margin = (first.margin||0) +"px";
// img.style.cssText += ';margin:' + (first.margin||0) +"px;" + 'border:' + (first.border||0) +"px solid #000";
domUtils.setAttributes(img, first);
me.execCommand('imagefloat', floatStyle);
if (opt.length > 0) {
range.setStartAfter(img).setCursor(false, true);
me.execCommand('insertimage', opt);
}
} else {
var html = [], str = '', ci;
ci = opt[0];
if (opt.length == 1) {
unhtmlData(ci);
str = ' ';
if (ci['floatStyle'] == 'center') {
str = '' + str + '
';
}
html.push(str);
} else {
for (var i = 0; ci = opt[i++];) {
unhtmlData(ci);
str = '
';
html.push(str);
}
}
me.execCommand('insertHtml', html.join(''));
}
me.fireEvent('afterinsertimage', opt)
}
};
// plugins/justify.js
/**
* 段落格式
* @file
* @since 1.2.6.1
*/
/**
* 段落对齐方式
* @command justify
* @method execCommand
* @param { String } cmd 命令字符串
* @param { String } align 对齐方式:left => 居左,right => 居右,center => 居中,justify => 两端对齐
* @example
* ```javascript
* editor.execCommand( 'justify', 'center' );
* ```
*/
/**
* 如果选区所在位置是段落区域,返回当前段落对齐方式
* @command justify
* @method queryCommandValue
* @param { String } cmd 命令字符串
* @return { String } 返回段落对齐方式
* @example
* ```javascript
* editor.queryCommandValue( 'justify' );
* ```
*/
UE.plugins['justify'] = function () {
var me = this,
block = domUtils.isBlockElm,
defaultValue = {
left: 1,
right: 1,
center: 1,
justify: 1
},
doJustify = function (range, style) {
var bookmark = range.createBookmark(),
filterFn = function (node) {
return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' && !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace(node);
};
range.enlarge(true);
var bookmark2 = range.createBookmark(),
current = domUtils.getNextDomNode(bookmark2.start, false, filterFn),
tmpRange = range.cloneRange(),
tmpNode;
while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
if (current.nodeType == 3 || !block(current)) {
tmpRange.setStartBefore(current);
while (current && current !== bookmark2.end && !block(current)) {
tmpNode = current;
current = domUtils.getNextDomNode(current, false, null, function (node) {
return !block(node);
});
}
tmpRange.setEndAfter(tmpNode);
var common = tmpRange.getCommonAncestor();
if (!domUtils.isBody(common) && block(common)) {
domUtils.setStyles(common, utils.isString(style) ? { 'text-align': style } : style);
current = common;
} else {
var p = range.document.createElement('p');
domUtils.setStyles(p, utils.isString(style) ? { 'text-align': style } : style);
var frag = tmpRange.extractContents();
p.appendChild(frag);
tmpRange.insertNode(p);
current = p;
}
current = domUtils.getNextDomNode(current, false, filterFn);
} else {
current = domUtils.getNextDomNode(current, true, filterFn);
}
}
return range.moveToBookmark(bookmark2).moveToBookmark(bookmark);
};
UE.commands['justify'] = {
execCommand: function (cmdName, align) {
var range = this.selection.getRange(),
txt;
//闭合时单独处理
if (range.collapsed) {
txt = this.document.createTextNode('p');
range.insertNode(txt);
}
doJustify(range, align);
if (txt) {
range.setStartBefore(txt).collapse(true);
domUtils.remove(txt);
}
range.select();
return true;
},
queryCommandValue: function () {
var startNode = this.selection.getStart(),
value = domUtils.getComputedStyle(startNode, 'text-align');
return defaultValue[value] ? value : 'left';
},
queryCommandState: function () {
var start = this.selection.getStart(),
cell = start && domUtils.findParentByTagName(start, ["td", "th", "caption"], true);
return cell ? -1 : 0;
}
};
};
// plugins/font.js
/**
* 字体颜色,背景色,字号,字体,下划线,删除线
* @file
* @since 1.2.6.1
*/
/**
* 字体颜色
* @command forecolor
* @method execCommand
* @param { String } cmd 命令字符串
* @param { String } value 色值(必须十六进制)
* @example
* ```javascript
* editor.execCommand( 'forecolor', '#000' );
* ```
*/
/**
* 返回选区字体颜色
* @command forecolor
* @method queryCommandValue
* @param { String } cmd 命令字符串
* @return { String } 返回字体颜色
* @example
* ```javascript
* editor.queryCommandValue( 'forecolor' );
* ```
*/
/**
* 字体背景颜色
* @command backcolor
* @method execCommand
* @param { String } cmd 命令字符串
* @param { String } value 色值(必须十六进制)
* @example
* ```javascript
* editor.execCommand( 'backcolor', '#000' );
* ```
*/
/**
* 返回选区字体颜色
* @command backcolor
* @method queryCommandValue
* @param { String } cmd 命令字符串
* @return { String } 返回字体背景颜色
* @example
* ```javascript
* editor.queryCommandValue( 'backcolor' );
* ```
*/
/**
* 字体大小
* @command fontsize
* @method execCommand
* @param { String } cmd 命令字符串
* @param { String } value 字体大小
* @example
* ```javascript
* editor.execCommand( 'fontsize', '14px' );
* ```
*/
/**
* 返回选区字体大小
* @command fontsize
* @method queryCommandValue
* @param { String } cmd 命令字符串
* @return { String } 返回字体大小
* @example
* ```javascript
* editor.queryCommandValue( 'fontsize' );
* ```
*/
/**
* 字体样式
* @command fontfamily
* @method execCommand
* @param { String } cmd 命令字符串
* @param { String } value 字体样式
* @example
* ```javascript
* editor.execCommand( 'fontfamily', '微软雅黑' );
* ```
*/
/**
* 返回选区字体样式
* @command fontfamily
* @method queryCommandValue
* @param { String } cmd 命令字符串
* @return { String } 返回字体样式
* @example
* ```javascript
* editor.queryCommandValue( 'fontfamily' );
* ```
*/
/**
* 字体下划线,与删除线互斥
* @command underline
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'underline' );
* ```
*/
/**
* 字体删除线,与下划线互斥
* @command strikethrough
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'strikethrough' );
* ```
*/
/**
* 字体边框
* @command fontborder
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'fontborder' );
* ```
*/
UE.plugins['font'] = function () {
var me = this,
fonts = {
'forecolor': 'color',
'backcolor': 'background-color',
'fontsize': 'font-size',
'fontfamily': 'font-family',
'underline': 'text-decoration',
'strikethrough': 'text-decoration',
'fontborder': 'border'
},
needCmd = { 'underline': 1, 'strikethrough': 1, 'fontborder': 1 },
needSetChild = {
'forecolor': 'color',
'backcolor': 'background-color',
'fontsize': 'font-size',
'fontfamily': 'font-family'
};
me.setOpt({
'fontfamily': [
{ name: 'songti', val: '宋体,SimSun' },
{ name: 'yahei', val: '微软雅黑,Microsoft YaHei' },
{ name: 'kaiti', val: '楷体,楷体_GB2312, SimKai' },
{ name: 'heiti', val: '黑体, SimHei' },
{ name: 'lishu', val: '隶书, SimLi' },
{ name: 'andaleMono', val: 'andale mono' },
{ name: 'arial', val: 'arial, helvetica,sans-serif' },
{ name: 'arialBlack', val: 'arial black,avant garde' },
{ name: 'comicSansMs', val: 'comic sans ms' },
{ name: 'impact', val: 'impact,chicago' },
{ name: 'timesNewRoman', val: 'times new roman' }
],
'fontsize': [10, 11, 12, 14, 16, 18, 20, 24, 36]
});
function mergeWithParent(node) {
var parent;
while (parent = node.parentNode) {
if (parent.tagName == 'SPAN' && domUtils.getChildCount(parent, function (child) {
return !domUtils.isBookmarkNode(child) && !domUtils.isBr(child)
}) == 1) {
parent.style.cssText += node.style.cssText;
domUtils.remove(node, true);
node = parent;
} else {
break;
}
}
}
function mergeChild(rng, cmdName, value) {
if (needSetChild[cmdName]) {
rng.adjustmentBoundary();
if (!rng.collapsed && rng.startContainer.nodeType == 1) {
var start = rng.startContainer.childNodes[rng.startOffset];
if (start && domUtils.isTagNode(start, 'span')) {
var bk = rng.createBookmark();
utils.each(domUtils.getElementsByTagName(start, 'span'), function (span) {
if (!span.parentNode || domUtils.isBookmarkNode(span)) return;
if (cmdName == 'backcolor' && domUtils.getComputedStyle(span, 'background-color').toLowerCase() === value) {
return;
}
domUtils.removeStyle(span, needSetChild[cmdName]);
if (span.style.cssText.replace(/^\s+$/, '').length == 0) {
domUtils.remove(span, true)
}
});
rng.moveToBookmark(bk)
}
}
}
}
function mergesibling(rng, cmdName, value) {
var collapsed = rng.collapsed,
bk = rng.createBookmark(), common;
if (collapsed) {
common = bk.start.parentNode;
while (dtd.$inline[common.tagName]) {
common = common.parentNode;
}
} else {
common = domUtils.getCommonAncestor(bk.start, bk.end);
}
utils.each(domUtils.getElementsByTagName(common, 'span'), function (span) {
if (!span.parentNode || domUtils.isBookmarkNode(span)) return;
if (/\s*border\s*:\s*none;?\s*/i.test(span.style.cssText)) {
if (/^\s*border\s*:\s*none;?\s*$/.test(span.style.cssText)) {
domUtils.remove(span, true);
} else {
domUtils.removeStyle(span, 'border');
}
return
}
if (/border/i.test(span.style.cssText) && span.parentNode.tagName == 'SPAN' && /border/i.test(span.parentNode.style.cssText)) {
span.style.cssText = span.style.cssText.replace(/border[^:]*:[^;]+;?/gi, '');
}
if (!(cmdName == 'fontborder' && value == 'none')) {
var next = span.nextSibling;
while (next && next.nodeType == 1 && next.tagName == 'SPAN') {
if (domUtils.isBookmarkNode(next) && cmdName == 'fontborder') {
span.appendChild(next);
next = span.nextSibling;
continue;
}
if (next.style.cssText == span.style.cssText) {
domUtils.moveChild(next, span);
domUtils.remove(next);
}
if (span.nextSibling === next)
break;
next = span.nextSibling;
}
}
mergeWithParent(span);
if (browser.ie && browser.version > 8) {
//拷贝父亲们的特别的属性,这里只做背景颜色的处理
var parent = domUtils.findParent(span, function (n) { return n.tagName == 'SPAN' && /background-color/.test(n.style.cssText) });
if (parent && !/background-color/.test(span.style.cssText)) {
span.style.backgroundColor = parent.style.backgroundColor;
}
}
});
rng.moveToBookmark(bk);
mergeChild(rng, cmdName, value)
}
me.addInputRule(function (root) {
utils.each(root.getNodesByTagName('u s del font strike'), function (node) {
if (node.tagName == 'font') {
var cssStyle = [];
for (var p in node.attrs) {
switch (p) {
case 'size':
cssStyle.push('font-size:' +
({
'1': '10',
'2': '12',
'3': '16',
'4': '18',
'5': '24',
'6': '32',
'7': '48'
}[node.attrs[p]] || node.attrs[p]) + 'px');
break;
case 'color':
cssStyle.push('color:' + node.attrs[p]);
break;
case 'face':
cssStyle.push('font-family:' + node.attrs[p]);
break;
case 'style':
cssStyle.push(node.attrs[p]);
}
}
node.attrs = {
'style': cssStyle.join(';')
};
} else {
var val = node.tagName == 'u' ? 'underline' : 'line-through';
node.attrs = {
'style': (node.getAttr('style') || '') + 'text-decoration:' + val + ';'
}
}
node.tagName = 'span';
});
// utils.each(root.getNodesByTagName('span'), function (node) {
// var val;
// if(val = node.getAttr('class')){
// if(/fontstrikethrough/.test(val)){
// node.setStyle('text-decoration','line-through');
// if(node.attrs['class']){
// node.attrs['class'] = node.attrs['class'].replace(/fontstrikethrough/,'');
// }else{
// node.setAttr('class')
// }
// }
// if(/fontborder/.test(val)){
// node.setStyle('border','1px solid #000');
// if(node.attrs['class']){
// node.attrs['class'] = node.attrs['class'].replace(/fontborder/,'');
// }else{
// node.setAttr('class')
// }
// }
// }
// });
});
// me.addOutputRule(function(root){
// utils.each(root.getNodesByTagName('span'), function (node) {
// var val;
// if(val = node.getStyle('text-decoration')){
// if(/line-through/.test(val)){
// if(node.attrs['class']){
// node.attrs['class'] += ' fontstrikethrough';
// }else{
// node.setAttr('class','fontstrikethrough')
// }
// }
//
// node.setStyle('text-decoration')
// }
// if(val = node.getStyle('border')){
// if(/1px/.test(val) && /solid/.test(val)){
// if(node.attrs['class']){
// node.attrs['class'] += ' fontborder';
//
// }else{
// node.setAttr('class','fontborder')
// }
// }
// node.setStyle('border')
//
// }
// });
// });
for (var p in fonts) {
(function (cmd, style) {
UE.commands[cmd] = {
execCommand: function (cmdName, value) {
value = value || (this.queryCommandState(cmdName) ? 'none' : cmdName == 'underline' ? 'underline' :
cmdName == 'fontborder' ? '1px solid #000' :
'line-through');
var me = this,
range = this.selection.getRange(),
text;
if (value == 'default') {
if (range.collapsed) {
text = me.document.createTextNode('font');
range.insertNode(text).select();
}
me.execCommand('removeFormat', 'span,a', style);
if (text) {
range.setStartBefore(text).collapse(true);
domUtils.remove(text);
}
mergesibling(range, cmdName, value);
range.select()
} else {
if (!range.collapsed) {
if (needCmd[cmd] && me.queryCommandValue(cmd)) {
me.execCommand('removeFormat', 'span,a', style);
}
range = me.selection.getRange();
range.applyInlineStyle('span', { 'style': style + ':' + value });
mergesibling(range, cmdName, value);
range.select();
} else {
var span = domUtils.findParentByTagName(range.startContainer, 'span', true);
text = me.document.createTextNode('font');
if (span && !span.children.length && !span[browser.ie ? 'innerText' : 'textContent'].replace(fillCharReg, '').length) {
//for ie hack when enter
range.insertNode(text);
if (needCmd[cmd]) {
range.selectNode(text).select();
me.execCommand('removeFormat', 'span,a', style, null);
span = domUtils.findParentByTagName(text, 'span', true);
range.setStartBefore(text);
}
span && (span.style.cssText += ';' + style + ':' + value);
range.collapse(true).select();
} else {
range.insertNode(text);
range.selectNode(text).select();
span = range.document.createElement('span');
if (needCmd[cmd]) {
//a标签内的不处理跳过
if (domUtils.findParentByTagName(text, 'a', true)) {
range.setStartBefore(text).setCursor();
domUtils.remove(text);
return;
}
me.execCommand('removeFormat', 'span,a', style);
}
span.style.cssText = style + ':' + value;
text.parentNode.insertBefore(span, text);
//修复,span套span 但样式不继承的问题
if (!browser.ie || browser.ie && browser.version == 9) {
var spanParent = span.parentNode;
while (!domUtils.isBlockElm(spanParent)) {
if (spanParent.tagName == 'SPAN') {
//opera合并style不会加入";"
span.style.cssText = spanParent.style.cssText + ";" + span.style.cssText;
}
spanParent = spanParent.parentNode;
}
}
if (opera) {
setTimeout(function () {
range.setStart(span, 0).collapse(true);
mergesibling(range, cmdName, value);
range.select();
});
} else {
range.setStart(span, 0).collapse(true);
mergesibling(range, cmdName, value);
range.select();
}
//trace:981
//domUtils.mergeToParent(span)
}
domUtils.remove(text);
}
}
return true;
},
queryCommandValue: function (cmdName) {
var startNode = this.selection.getStart();
//trace:946
if (cmdName == 'underline' || cmdName == 'strikethrough') {
var tmpNode = startNode, value;
while (tmpNode && !domUtils.isBlockElm(tmpNode) && !domUtils.isBody(tmpNode)) {
if (tmpNode.nodeType == 1) {
value = domUtils.getComputedStyle(tmpNode, style);
if (value != 'none') {
return value;
}
}
tmpNode = tmpNode.parentNode;
}
return 'none';
}
if (cmdName == 'fontborder') {
var tmp = startNode, val;
while (tmp && dtd.$inline[tmp.tagName]) {
if (val = domUtils.getComputedStyle(tmp, 'border')) {
if (/1px/.test(val) && /solid/.test(val)) {
return val;
}
}
tmp = tmp.parentNode;
}
return ''
}
if (cmdName == 'FontSize') {
var styleVal = domUtils.getComputedStyle(startNode, style),
tmp = /^([\d\.]+)(\w+)$/.exec(styleVal);
if (tmp) {
return Math.floor(tmp[1]) + tmp[2];
}
return styleVal;
}
return domUtils.getComputedStyle(startNode, style);
},
queryCommandState: function (cmdName) {
if (!needCmd[cmdName])
return 0;
var val = this.queryCommandValue(cmdName);
if (cmdName == 'fontborder') {
return /1px/.test(val) && /solid/.test(val)
} else {
return cmdName == 'underline' ? /underline/.test(val) : /line\-through/.test(val);
}
}
};
})(p, fonts[p]);
}
};
// plugins/link.js
/**
* 超链接
* @file
* @since 1.2.6.1
*/
/**
* 插入超链接
* @command link
* @method execCommand
* @param { String } cmd 命令字符串
* @param { Object } options 设置自定义属性,例如:url、title、target
* @example
* ```javascript
* editor.execCommand( 'link', '{
* url:'ueditor.baidu.com',
* title:'ueditor',
* target:'_blank'
* }' );
* ```
*/
/**
* 返回当前选中的第一个超链接节点
* @command link
* @method queryCommandValue
* @param { String } cmd 命令字符串
* @return { Element } 超链接节点
* @example
* ```javascript
* editor.queryCommandValue( 'link' );
* ```
*/
/**
* 取消超链接
* @command unlink
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'unlink');
* ```
*/
UE.plugins['link'] = function () {
function optimize(range) {
var start = range.startContainer, end = range.endContainer;
if (start = domUtils.findParentByTagName(start, 'a', true)) {
range.setStartBefore(start);
}
if (end = domUtils.findParentByTagName(end, 'a', true)) {
range.setEndAfter(end);
}
}
UE.commands['unlink'] = {
execCommand: function () {
var range = this.selection.getRange(),
bookmark;
if (range.collapsed && !domUtils.findParentByTagName(range.startContainer, 'a', true)) {
return;
}
bookmark = range.createBookmark();
optimize(range);
range.removeInlineStyle('a').moveToBookmark(bookmark).select();
},
queryCommandState: function () {
return !this.highlight && this.queryCommandValue('link') ? 0 : -1;
}
};
function doLink(range, opt, me) {
var rngClone = range.cloneRange(),
link = me.queryCommandValue('link');
optimize(range = range.adjustmentBoundary());
var start = range.startContainer;
if (start.nodeType == 1 && link) {
start = start.childNodes[range.startOffset];
if (start && start.nodeType == 1 && start.tagName == 'A' && /^(?:https?|ftp|file)\s*:\s*\/\//.test(start[browser.ie ? 'innerText' : 'textContent'])) {
start[browser.ie ? 'innerText' : 'textContent'] = utils.html(opt.textValue || opt.href);
}
}
if (!rngClone.collapsed || link) {
range.removeInlineStyle('a');
rngClone = range.cloneRange();
}
if (rngClone.collapsed) {
var a = range.document.createElement('a'),
text = '';
if (opt.textValue) {
text = utils.html(opt.textValue);
delete opt.textValue;
} else {
text = utils.html(opt.href);
}
domUtils.setAttributes(a, opt);
start = domUtils.findParentByTagName(rngClone.startContainer, 'a', true);
if (start && domUtils.isInNodeEndBoundary(rngClone, start)) {
range.setStartAfter(start).collapse(true);
}
a[browser.ie ? 'innerText' : 'textContent'] = text;
range.insertNode(a).selectNode(a);
} else {
range.applyInlineStyle('a', opt);
}
}
UE.commands['link'] = {
execCommand: function (cmdName, opt) {
var range;
opt._href && (opt._href = utils.unhtml(opt._href, /[<">]/g));
opt.href && (opt.href = utils.unhtml(opt.href, /[<">]/g));
opt.textValue && (opt.textValue = utils.unhtml(opt.textValue, /[<">]/g));
doLink(range = this.selection.getRange(), opt, this);
//闭合都不加占位符,如果加了会在a后边多个占位符节点,导致a是图片背景组成的列表,出现空白问题
range.collapse().select(true);
},
queryCommandValue: function () {
var range = this.selection.getRange(),
node;
if (range.collapsed) {
// node = this.selection.getStart();
//在ie下getstart()取值偏上了
node = range.startContainer;
node = node.nodeType == 1 ? node : node.parentNode;
if (node && (node = domUtils.findParentByTagName(node, 'a', true)) && !domUtils.isInNodeEndBoundary(range, node)) {
return node;
}
} else {
//trace:1111 如果是xx
startContainer是p就会找不到a
range.shrinkBoundary();
var start = range.startContainer.nodeType == 3 || !range.startContainer.childNodes[range.startOffset] ? range.startContainer : range.startContainer.childNodes[range.startOffset],
end = range.endContainer.nodeType == 3 || range.endOffset == 0 ? range.endContainer : range.endContainer.childNodes[range.endOffset - 1],
common = range.getCommonAncestor();
node = domUtils.findParentByTagName(common, 'a', true);
if (!node && common.nodeType == 1) {
var as = common.getElementsByTagName('a'),
ps, pe;
for (var i = 0, ci; ci = as[i++];) {
ps = domUtils.getPosition(ci, start), pe = domUtils.getPosition(ci, end);
if ((ps & domUtils.POSITION_FOLLOWING || ps & domUtils.POSITION_CONTAINS)
&&
(pe & domUtils.POSITION_PRECEDING || pe & domUtils.POSITION_CONTAINS)
) {
node = ci;
break;
}
}
}
return node;
}
},
queryCommandState: function () {
//判断如果是视频的话连接不可用
//fix 853
var img = this.selection.getRange().getClosedNode(),
flag = img && (img.className == "edui-faked-video" || img.className.indexOf("edui-upload-video") != -1);
return flag ? -1 : 0;
}
};
};
// plugins/iframe.js
///import core
///import plugins\inserthtml.js
///commands 插入框架
///commandsName InsertFrame
///commandsTitle 插入Iframe
///commandsDialog dialogs\insertframe
UE.plugins['insertframe'] = function () {
var me = this;
function deleteIframe() {
me._iframe && delete me._iframe;
}
me.addListener("selectionchange", function () {
deleteIframe();
});
};
// plugins/scrawl.js
///import core
///commands 涂鸦
///commandsName Scrawl
///commandsTitle 涂鸦
///commandsDialog dialogs\scrawl
UE.commands['scrawl'] = {
queryCommandState: function () {
return (browser.ie && browser.version <= 8) ? -1 : 0;
}
};
// plugins/removeformat.js
/**
* 清除格式
* @file
* @since 1.2.6.1
*/
/**
* 清除文字样式
* @command removeformat
* @method execCommand
* @param { String } cmd 命令字符串
* @param {String} tags 以逗号隔开的标签。如:strong
* @param {String} style 样式如:color
* @param {String} attrs 属性如:width
* @example
* ```javascript
* editor.execCommand( 'removeformat', 'strong','color','width' );
* ```
*/
UE.plugins['removeformat'] = function () {
var me = this;
me.setOpt({
'removeFormatTags': 'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var',
'removeFormatAttributes': 'class,style,lang,width,height,align,hspace,valign'
});
me.commands['removeformat'] = {
execCommand: function (cmdName, tags, style, attrs, notIncludeA) {
var tagReg = new RegExp('^(?:' + (tags || this.options.removeFormatTags).replace(/,/g, '|') + ')$', 'i'),
removeFormatAttributes = style ? [] : (attrs || this.options.removeFormatAttributes).split(','),
range = new dom.Range(this.document),
bookmark, node, parent,
filter = function (node) {
return node.nodeType == 1;
};
function isRedundantSpan(node) {
if (node.nodeType == 3 || node.tagName.toLowerCase() != 'span') {
return 0;
}
if (browser.ie) {
//ie 下判断实效,所以只能简单用style来判断
//return node.style.cssText == '' ? 1 : 0;
var attrs = node.attributes;
if (attrs.length) {
for (var i = 0, l = attrs.length; i < l; i++) {
if (attrs[i].specified) {
return 0;
}
}
return 1;
}
}
return !node.attributes.length;
}
function doRemove(range) {
var bookmark1 = range.createBookmark();
if (range.collapsed) {
range.enlarge(true);
}
//不能把a标签切了
if (!notIncludeA) {
var aNode = domUtils.findParentByTagName(range.startContainer, 'a', true);
if (aNode) {
range.setStartBefore(aNode);
}
aNode = domUtils.findParentByTagName(range.endContainer, 'a', true);
if (aNode) {
range.setEndAfter(aNode);
}
}
bookmark = range.createBookmark();
node = bookmark.start;
//切开始
while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) {
domUtils.breakParent(node, parent);
domUtils.clearEmptySibling(node);
}
if (bookmark.end) {
//切结束
node = bookmark.end;
while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) {
domUtils.breakParent(node, parent);
domUtils.clearEmptySibling(node);
}
//开始去除样式
var current = domUtils.getNextDomNode(bookmark.start, false, filter),
next;
while (current) {
if (current == bookmark.end) {
break;
}
next = domUtils.getNextDomNode(current, true, filter);
if (!dtd.$empty[current.tagName.toLowerCase()] && !domUtils.isBookmarkNode(current)) {
if (tagReg.test(current.tagName)) {
if (style) {
domUtils.removeStyle(current, style);
if (isRedundantSpan(current) && style != 'text-decoration') {
domUtils.remove(current, true);
}
} else {
domUtils.remove(current, true);
}
} else {
//trace:939 不能把list上的样式去掉
if (!dtd.$tableContent[current.tagName] && !dtd.$list[current.tagName]) {
domUtils.removeAttributes(current, removeFormatAttributes);
if (isRedundantSpan(current)) {
domUtils.remove(current, true);
}
}
}
}
current = next;
}
}
//trace:1035
//trace:1096 不能把td上的样式去掉,比如边框
var pN = bookmark.start.parentNode;
if (domUtils.isBlockElm(pN) && !dtd.$tableContent[pN.tagName] && !dtd.$list[pN.tagName]) {
domUtils.removeAttributes(pN, removeFormatAttributes);
}
pN = bookmark.end.parentNode;
if (bookmark.end && domUtils.isBlockElm(pN) && !dtd.$tableContent[pN.tagName] && !dtd.$list[pN.tagName]) {
domUtils.removeAttributes(pN, removeFormatAttributes);
}
range.moveToBookmark(bookmark).moveToBookmark(bookmark1);
//清除冗余的代码
var node = range.startContainer,
tmp,
collapsed = range.collapsed;
while (node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]) {
tmp = node.parentNode;
range.setStartBefore(node);
//trace:937
//更新结束边界
if (range.startContainer === range.endContainer) {
range.endOffset--;
}
domUtils.remove(node);
node = tmp;
}
if (!collapsed) {
node = range.endContainer;
while (node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]) {
tmp = node.parentNode;
range.setEndBefore(node);
domUtils.remove(node);
node = tmp;
}
}
}
range = this.selection.getRange();
doRemove(range);
range.select();
}
};
};
// plugins/blockquote.js
/**
* 添加引用
* @file
* @since 1.2.6.1
*/
/**
* 添加引用
* @command blockquote
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'blockquote' );
* ```
*/
/**
* 添加引用
* @command blockquote
* @method execCommand
* @param { String } cmd 命令字符串
* @param { Object } attrs 节点属性
* @example
* ```javascript
* editor.execCommand( 'blockquote',{
* style: "color: red;"
* } );
* ```
*/
UE.plugins['blockquote'] = function () {
var me = this;
function getObj(editor) {
return domUtils.filterNodeList(editor.selection.getStartElementPath(), 'blockquote');
}
me.commands['blockquote'] = {
execCommand: function (cmdName, attrs) {
var range = this.selection.getRange(),
obj = getObj(this),
blockquote = dtd.blockquote,
bookmark = range.createBookmark();
if (obj) {
var start = range.startContainer,
startBlock = domUtils.isBlockElm(start) ? start : domUtils.findParent(start, function (node) { return domUtils.isBlockElm(node) }),
end = range.endContainer,
endBlock = domUtils.isBlockElm(end) ? end : domUtils.findParent(end, function (node) { return domUtils.isBlockElm(node) });
//处理一下li
startBlock = domUtils.findParentByTagName(startBlock, 'li', true) || startBlock;
endBlock = domUtils.findParentByTagName(endBlock, 'li', true) || endBlock;
if (startBlock.tagName == 'LI' || startBlock.tagName == 'TD' || startBlock === obj || domUtils.isBody(startBlock)) {
domUtils.remove(obj, true);
} else {
domUtils.breakParent(startBlock, obj);
}
if (startBlock !== endBlock) {
obj = domUtils.findParentByTagName(endBlock, 'blockquote');
if (obj) {
if (endBlock.tagName == 'LI' || endBlock.tagName == 'TD' || domUtils.isBody(endBlock)) {
obj.parentNode && domUtils.remove(obj, true);
} else {
domUtils.breakParent(endBlock, obj);
}
}
}
var blockquotes = domUtils.getElementsByTagName(this.document, 'blockquote');
for (var i = 0, bi; bi = blockquotes[i++];) {
if (!bi.childNodes.length) {
domUtils.remove(bi);
} else if (domUtils.getPosition(bi, startBlock) & domUtils.POSITION_FOLLOWING && domUtils.getPosition(bi, endBlock) & domUtils.POSITION_PRECEDING) {
domUtils.remove(bi, true);
}
}
} else {
var tmpRange = range.cloneRange(),
node = tmpRange.startContainer.nodeType == 1 ? tmpRange.startContainer : tmpRange.startContainer.parentNode,
preNode = node,
doEnd = 1;
//调整开始
while (1) {
if (domUtils.isBody(node)) {
if (preNode !== node) {
if (range.collapsed) {
tmpRange.selectNode(preNode);
doEnd = 0;
} else {
tmpRange.setStartBefore(preNode);
}
} else {
tmpRange.setStart(node, 0);
}
break;
}
if (!blockquote[node.tagName]) {
if (range.collapsed) {
tmpRange.selectNode(preNode);
} else {
tmpRange.setStartBefore(preNode);
}
break;
}
preNode = node;
node = node.parentNode;
}
//调整结束
if (doEnd) {
preNode = node = node = tmpRange.endContainer.nodeType == 1 ? tmpRange.endContainer : tmpRange.endContainer.parentNode;
while (1) {
if (domUtils.isBody(node)) {
if (preNode !== node) {
tmpRange.setEndAfter(preNode);
} else {
tmpRange.setEnd(node, node.childNodes.length);
}
break;
}
if (!blockquote[node.tagName]) {
tmpRange.setEndAfter(preNode);
break;
}
preNode = node;
node = node.parentNode;
}
}
node = range.document.createElement('blockquote');
domUtils.setAttributes(node, attrs);
node.appendChild(tmpRange.extractContents());
tmpRange.insertNode(node);
//去除重复的
var childs = domUtils.getElementsByTagName(node, 'blockquote');
for (var i = 0, ci; ci = childs[i++];) {
if (ci.parentNode) {
domUtils.remove(ci, true);
}
}
}
range.moveToBookmark(bookmark).select();
},
queryCommandState: function () {
return getObj(this) ? 1 : 0;
}
};
};
// plugins/convertcase.js
/**
* 大小写转换
* @file
* @since 1.2.6.1
*/
/**
* 把选区内文本变大写,与“tolowercase”命令互斥
* @command touppercase
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'touppercase' );
* ```
*/
/**
* 把选区内文本变小写,与“touppercase”命令互斥
* @command tolowercase
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'tolowercase' );
* ```
*/
UE.commands['touppercase'] =
UE.commands['tolowercase'] = {
execCommand: function (cmd) {
var me = this;
var rng = me.selection.getRange();
if (rng.collapsed) {
return rng;
}
var bk = rng.createBookmark(),
bkEnd = bk.end,
filterFn = function (node) {
return !domUtils.isBr(node) && !domUtils.isWhitespace(node);
},
curNode = domUtils.getNextDomNode(bk.start, false, filterFn);
while (curNode && (domUtils.getPosition(curNode, bkEnd) & domUtils.POSITION_PRECEDING)) {
if (curNode.nodeType == 3) {
curNode.nodeValue = curNode.nodeValue[cmd == 'touppercase' ? 'toUpperCase' : 'toLowerCase']();
}
curNode = domUtils.getNextDomNode(curNode, true, filterFn);
if (curNode === bkEnd) {
break;
}
}
rng.moveToBookmark(bk).select();
}
};
// plugins/indent.js
/**
* 首行缩进
* @file
* @since 1.2.6.1
*/
/**
* 缩进
* @command indent
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'indent' );
* ```
*/
UE.commands['indent'] = {
execCommand: function () {
var me = this, value = me.queryCommandState("indent") ? "0em" : (me.options.indentValue || '2em');
me.execCommand('Paragraph', 'p', { style: 'text-indent:' + value });
},
queryCommandState: function () {
var pN = domUtils.filterNodeList(this.selection.getStartElementPath(), 'p h1 h2 h3 h4 h5 h6');
return pN && pN.style.textIndent && parseInt(pN.style.textIndent) ? 1 : 0;
}
};
// plugins/print.js
/**
* 打印
* @file
* @since 1.2.6.1
*/
/**
* 打印
* @command print
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'print' );
* ```
*/
UE.commands['print'] = {
execCommand: function () {
this.window.print();
},
notNeedUndo: 1
};
// plugins/preview.js
/**
* 预览
* @file
* @since 1.2.6.1
*/
/**
* 预览
* @command preview
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'preview' );
* ```
*/
UE.commands['preview'] = {
execCommand: function () {
var w = window.open('', '_blank', ''),
d = w.document;
d.open();
d.write('' + this.getContent(null, null, true) + '
');
d.close();
},
notNeedUndo: 1
};
// plugins/selectall.js
/**
* 全选
* @file
* @since 1.2.6.1
*/
/**
* 选中所有内容
* @command selectall
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'selectall' );
* ```
*/
UE.plugins['selectall'] = function () {
var me = this;
me.commands['selectall'] = {
execCommand: function () {
//去掉了原生的selectAll,因为会出现报错和当内容为空时,不能出现闭合状态的光标
var me = this, body = me.body,
range = me.selection.getRange();
range.selectNodeContents(body);
if (domUtils.isEmptyBlock(body)) {
//opera不能自动合并到元素的里边,要手动处理一下
if (browser.opera && body.firstChild && body.firstChild.nodeType == 1) {
range.setStartAtFirst(body.firstChild);
}
range.collapse(true);
}
range.select(true);
},
notNeedUndo: 1
};
//快捷键
me.addshortcutkey({
"selectAll": "ctrl+65"
});
};
// plugins/paragraph.js
/**
* 段落样式
* @file
* @since 1.2.6.1
*/
/**
* 段落格式
* @command paragraph
* @method execCommand
* @param { String } cmd 命令字符串
* @param {String} style 标签值为:'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'
* @param {Object} attrs 标签的属性
* @example
* ```javascript
* editor.execCommand( 'Paragraph','h1','{
* class:'test'
* }' );
* ```
*/
/**
* 返回选区内节点标签名
* @command paragraph
* @method queryCommandValue
* @param { String } cmd 命令字符串
* @return { String } 节点标签名
* @example
* ```javascript
* editor.queryCommandValue( 'Paragraph' );
* ```
*/
UE.plugins['paragraph'] = function () {
var me = this,
block = domUtils.isBlockElm,
notExchange = ['TD', 'LI', 'PRE'],
doParagraph = function (range, style, attrs, sourceCmdName) {
var bookmark = range.createBookmark(),
filterFn = function (node) {
return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' && !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace(node);
},
para;
range.enlarge(true);
var bookmark2 = range.createBookmark(),
current = domUtils.getNextDomNode(bookmark2.start, false, filterFn),
tmpRange = range.cloneRange(),
tmpNode;
while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
if (current.nodeType == 3 || !block(current)) {
tmpRange.setStartBefore(current);
while (current && current !== bookmark2.end && !block(current)) {
tmpNode = current;
current = domUtils.getNextDomNode(current, false, null, function (node) {
return !block(node);
});
}
tmpRange.setEndAfter(tmpNode);
para = range.document.createElement(style);
if (attrs) {
domUtils.setAttributes(para, attrs);
if (sourceCmdName && sourceCmdName == 'customstyle' && attrs.style) {
para.style.cssText = attrs.style;
}
}
para.appendChild(tmpRange.extractContents());
//需要内容占位
if (domUtils.isEmptyNode(para)) {
domUtils.fillChar(range.document, para);
}
tmpRange.insertNode(para);
var parent = para.parentNode;
//如果para上一级是一个block元素且不是body,td就删除它
if (block(parent) && !domUtils.isBody(para.parentNode) && utils.indexOf(notExchange, parent.tagName) == -1) {
//存储dir,style
if (!(sourceCmdName && sourceCmdName == 'customstyle')) {
parent.getAttribute('dir') && para.setAttribute('dir', parent.getAttribute('dir'));
//trace:1070
parent.style.cssText && (para.style.cssText = parent.style.cssText + ';' + para.style.cssText);
//trace:1030
parent.style.textAlign && !para.style.textAlign && (para.style.textAlign = parent.style.textAlign);
parent.style.textIndent && !para.style.textIndent && (para.style.textIndent = parent.style.textIndent);
parent.style.padding && !para.style.padding && (para.style.padding = parent.style.padding);
}
//trace:1706 选择的就是h1-6要删除
if (attrs && /h\d/i.test(parent.tagName) && !/h\d/i.test(para.tagName)) {
domUtils.setAttributes(parent, attrs);
if (sourceCmdName && sourceCmdName == 'customstyle' && attrs.style) {
parent.style.cssText = attrs.style;
}
domUtils.remove(para, true);
para = parent;
} else {
domUtils.remove(para.parentNode, true);
}
}
if (utils.indexOf(notExchange, parent.tagName) != -1) {
current = parent;
} else {
current = para;
}
current = domUtils.getNextDomNode(current, false, filterFn);
} else {
current = domUtils.getNextDomNode(current, true, filterFn);
}
}
return range.moveToBookmark(bookmark2).moveToBookmark(bookmark);
};
me.setOpt('paragraph', { 'p': '', 'h1': '', 'h2': '', 'h3': '', 'h4': '', 'h5': '', 'h6': '' });
me.commands['paragraph'] = {
execCommand: function (cmdName, style, attrs, sourceCmdName) {
var range = this.selection.getRange();
//闭合时单独处理
if (range.collapsed) {
var txt = this.document.createTextNode('p');
range.insertNode(txt);
//去掉冗余的fillchar
if (browser.ie) {
var node = txt.previousSibling;
if (node && domUtils.isWhitespace(node)) {
domUtils.remove(node);
}
node = txt.nextSibling;
if (node && domUtils.isWhitespace(node)) {
domUtils.remove(node);
}
}
}
range = doParagraph(range, style, attrs, sourceCmdName);
if (txt) {
range.setStartBefore(txt).collapse(true);
pN = txt.parentNode;
domUtils.remove(txt);
if (domUtils.isBlockElm(pN) && domUtils.isEmptyNode(pN)) {
domUtils.fillNode(this.document, pN);
}
}
if (browser.gecko && range.collapsed && range.startContainer.nodeType == 1) {
var child = range.startContainer.childNodes[range.startOffset];
if (child && child.nodeType == 1 && child.tagName.toLowerCase() == style) {
range.setStart(child, 0).collapse(true);
}
}
//trace:1097 原来有true,原因忘了,但去了就不能清除多余的占位符了
range.select();
return true;
},
queryCommandValue: function () {
var node = domUtils.filterNodeList(this.selection.getStartElementPath(), 'p h1 h2 h3 h4 h5 h6');
return node ? node.tagName.toLowerCase() : '';
}
};
};
// plugins/directionality.js
/**
* 设置文字输入的方向的插件
* @file
* @since 1.2.6.1
*/
(function () {
var block = domUtils.isBlockElm,
getObj = function (editor) {
// var startNode = editor.selection.getStart(),
// parents;
// if ( startNode ) {
// //查找所有的是block的父亲节点
// parents = domUtils.findParents( startNode, true, block, true );
// for ( var i = 0,ci; ci = parents[i++]; ) {
// if ( ci.getAttribute( 'dir' ) ) {
// return ci;
// }
// }
// }
return domUtils.filterNodeList(editor.selection.getStartElementPath(), function (n) { return n && n.nodeType == 1 && n.getAttribute('dir') });
},
doDirectionality = function (range, editor, forward) {
var bookmark,
filterFn = function (node) {
return node.nodeType == 1 ? !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace(node);
},
obj = getObj(editor);
if (obj && range.collapsed) {
obj.setAttribute('dir', forward);
return range;
}
bookmark = range.createBookmark();
range.enlarge(true);
var bookmark2 = range.createBookmark(),
current = domUtils.getNextDomNode(bookmark2.start, false, filterFn),
tmpRange = range.cloneRange(),
tmpNode;
while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
if (current.nodeType == 3 || !block(current)) {
tmpRange.setStartBefore(current);
while (current && current !== bookmark2.end && !block(current)) {
tmpNode = current;
current = domUtils.getNextDomNode(current, false, null, function (node) {
return !block(node);
});
}
tmpRange.setEndAfter(tmpNode);
var common = tmpRange.getCommonAncestor();
if (!domUtils.isBody(common) && block(common)) {
//遍历到了block节点
common.setAttribute('dir', forward);
current = common;
} else {
//没有遍历到,添加一个block节点
var p = range.document.createElement('p');
p.setAttribute('dir', forward);
var frag = tmpRange.extractContents();
p.appendChild(frag);
tmpRange.insertNode(p);
current = p;
}
current = domUtils.getNextDomNode(current, false, filterFn);
} else {
current = domUtils.getNextDomNode(current, true, filterFn);
}
}
return range.moveToBookmark(bookmark2).moveToBookmark(bookmark);
};
/**
* 文字输入方向
* @command directionality
* @method execCommand
* @param { String } cmdName 命令字符串
* @param { String } forward 传入'ltr'表示从左向右输入,传入'rtl'表示从右向左输入
* @example
* ```javascript
* editor.execCommand( 'directionality', 'ltr');
* ```
*/
/**
* 查询当前选区的文字输入方向
* @command directionality
* @method queryCommandValue
* @param { String } cmdName 命令字符串
* @return { String } 返回'ltr'表示从左向右输入,返回'rtl'表示从右向左输入
* @example
* ```javascript
* editor.queryCommandValue( 'directionality');
* ```
*/
UE.commands['directionality'] = {
execCommand: function (cmdName, forward) {
var range = this.selection.getRange();
//闭合时单独处理
if (range.collapsed) {
var txt = this.document.createTextNode('d');
range.insertNode(txt);
}
doDirectionality(range, this, forward);
if (txt) {
range.setStartBefore(txt).collapse(true);
domUtils.remove(txt);
}
range.select();
return true;
},
queryCommandValue: function () {
var node = getObj(this);
return node ? node.getAttribute('dir') : 'ltr';
}
};
})();
// plugins/horizontal.js
/**
* 插入分割线插件
* @file
* @since 1.2.6.1
*/
/**
* 插入分割线
* @command horizontal
* @method execCommand
* @param { String } cmdName 命令字符串
* @example
* ```javascript
* editor.execCommand( 'horizontal' );
* ```
*/
UE.plugins['horizontal'] = function () {
var me = this;
me.commands['horizontal'] = {
execCommand: function (cmdName) {
var me = this;
if (me.queryCommandState(cmdName) !== -1) {
me.execCommand('insertHtml', ' ');
var range = me.selection.getRange(),
start = range.startContainer;
if (start.nodeType == 1 && !start.childNodes[range.startOffset]) {
var tmp;
if (tmp = start.childNodes[range.startOffset - 1]) {
if (tmp.nodeType == 1 && tmp.tagName == 'HR') {
if (me.options.enterTag == 'p') {
tmp = me.document.createElement('p');
range.insertNode(tmp);
range.setStart(tmp, 0).setCursor();
} else {
tmp = me.document.createElement('br');
range.insertNode(tmp);
range.setStartBefore(tmp).setCursor();
}
}
}
}
return true;
}
},
//边界在table里不能加分隔线
queryCommandState: function () {
return domUtils.filterNodeList(this.selection.getStartElementPath(), 'table') ? -1 : 0;
}
};
// me.addListener('delkeyup',function(){
// var rng = this.selection.getRange();
// if(browser.ie && browser.version > 8){
// rng.txtToElmBoundary(true);
// if(domUtils.isStartInblock(rng)){
// var tmpNode = rng.startContainer;
// var pre = tmpNode.previousSibling;
// if(pre && domUtils.isTagNode(pre,'hr')){
// domUtils.remove(pre);
// rng.select();
// return;
// }
// }
// }
// if(domUtils.isBody(rng.startContainer)){
// var hr = rng.startContainer.childNodes[rng.startOffset -1];
// if(hr && hr.nodeName == 'HR'){
// var next = hr.nextSibling;
// if(next){
// rng.setStart(next,0)
// }else if(hr.previousSibling){
// rng.setStartAtLast(hr.previousSibling)
// }else{
// var p = this.document.createElement('p');
// hr.parentNode.insertBefore(p,hr);
// domUtils.fillNode(this.document,p);
// rng.setStart(p,0);
// }
// domUtils.remove(hr);
// rng.setCursor(false,true);
// }
// }
// })
me.addListener('delkeydown', function (name, evt) {
var rng = this.selection.getRange();
rng.txtToElmBoundary(true);
if (domUtils.isStartInblock(rng)) {
var tmpNode = rng.startContainer;
var pre = tmpNode.previousSibling;
if (pre && domUtils.isTagNode(pre, 'hr')) {
domUtils.remove(pre);
rng.select();
domUtils.preventDefault(evt);
return true;
}
}
})
};
// plugins/time.js
/**
* 插入时间和日期
* @file
* @since 1.2.6.1
*/
/**
* 插入时间,默认格式:12:59:59
* @command time
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'time');
* ```
*/
/**
* 插入日期,默认格式:2013-08-30
* @command date
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'date');
* ```
*/
UE.commands['time'] = UE.commands["date"] = {
execCommand: function (cmd, format) {
var date = new Date;
function formatTime(date, format) {
var hh = ('0' + date.getHours()).slice(-2),
ii = ('0' + date.getMinutes()).slice(-2),
ss = ('0' + date.getSeconds()).slice(-2);
format = format || 'hh:ii:ss';
return format.replace(/hh/ig, hh).replace(/ii/ig, ii).replace(/ss/ig, ss);
}
function formatDate(date, format) {
var yyyy = ('000' + date.getFullYear()).slice(-4),
yy = yyyy.slice(-2),
mm = ('0' + (date.getMonth() + 1)).slice(-2),
dd = ('0' + date.getDate()).slice(-2);
format = format || 'yyyy-mm-dd';
return format.replace(/yyyy/ig, yyyy).replace(/yy/ig, yy).replace(/mm/ig, mm).replace(/dd/ig, dd);
}
this.execCommand('insertHtml', cmd == "time" ? formatTime(date, format) : formatDate(date, format));
}
};
// plugins/rowspacing.js
/**
* 段前段后间距插件
* @file
* @since 1.2.6.1
*/
/**
* 设置段间距
* @command rowspacing
* @method execCommand
* @param { String } cmd 命令字符串
* @param { String } value 段间距的值,以px为单位
* @param { String } dir 间距位置,top或bottom,分别表示段前和段后
* @example
* ```javascript
* editor.execCommand( 'rowspacing', '10', 'top' );
* ```
*/
UE.plugins['rowspacing'] = function () {
var me = this;
me.setOpt({
'rowspacingtop': ['5', '10', '15', '20', '25'],
'rowspacingbottom': ['5', '10', '15', '20', '25']
});
me.commands['rowspacing'] = {
execCommand: function (cmdName, value, dir) {
this.execCommand('paragraph', 'p', { style: 'margin-' + dir + ':' + value + 'px' });
return true;
},
queryCommandValue: function (cmdName, dir) {
var pN = domUtils.filterNodeList(this.selection.getStartElementPath(), function (node) { return domUtils.isBlockElm(node) }),
value;
//trace:1026
if (pN) {
value = domUtils.getComputedStyle(pN, 'margin-' + dir).replace(/[^\d]/g, '');
return !value ? 0 : value;
}
return 0;
}
};
};
// plugins/lineheight.js
/**
* 设置行内间距
* @file
* @since 1.2.6.1
*/
UE.plugins['lineheight'] = function () {
var me = this;
me.setOpt({ 'lineheight': ['1', '1.5', '1.75', '2', '3', '4', '5'] });
/**
* 行距
* @command lineheight
* @method execCommand
* @param { String } cmdName 命令字符串
* @param { String } value 传入的行高值, 该值是当前字体的倍数, 例如: 1.5, 1.75
* @example
* ```javascript
* editor.execCommand( 'lineheight', 1.5);
* ```
*/
/**
* 查询当前选区内容的行高大小
* @command lineheight
* @method queryCommandValue
* @param { String } cmd 命令字符串
* @return { String } 返回当前行高大小
* @example
* ```javascript
* editor.queryCommandValue( 'lineheight' );
* ```
*/
me.commands['lineheight'] = {
execCommand: function (cmdName, value) {
this.execCommand('paragraph', 'p', { style: 'line-height:' + (value == "1" ? "normal" : value + 'em') });
return true;
},
queryCommandValue: function () {
var pN = domUtils.filterNodeList(this.selection.getStartElementPath(), function (node) { return domUtils.isBlockElm(node) });
if (pN) {
var value = domUtils.getComputedStyle(pN, 'line-height');
return value == 'normal' ? 1 : value.replace(/[^\d.]*/ig, "");
}
}
};
};
// plugins/insertcode.js
/**
* 插入代码插件
* @file
* @since 1.2.6.1
*/
UE.plugins['insertcode'] = function () {
var me = this;
me.ready(function () {
utils.cssRule('pre', 'pre{margin:.5em 0;padding:.4em .6em;border-radius:8px;background:#f8f8f8;}',
me.document)
});
me.setOpt('insertcode', {
'as3': 'ActionScript3',
'bash': 'Bash/Shell',
'cpp': 'C/C++',
'css': 'Css',
'cf': 'CodeFunction',
'c#': 'C#',
'delphi': 'Delphi',
'diff': 'Diff',
'erlang': 'Erlang',
'groovy': 'Groovy',
'html': 'Html',
'java': 'Java',
'jfx': 'JavaFx',
'js': 'Javascript',
'pl': 'Perl',
'php': 'Php',
'plain': 'Plain Text',
'ps': 'PowerShell',
'python': 'Python',
'ruby': 'Ruby',
'scala': 'Scala',
'sql': 'Sql',
'vb': 'Vb',
'xml': 'Xml'
});
/**
* 插入代码
* @command insertcode
* @method execCommand
* @param { String } cmd 命令字符串
* @param { String } lang 插入代码的语言
* @example
* ```javascript
* editor.execCommand( 'insertcode', 'javascript' );
* ```
*/
/**
* 如果选区所在位置是插入插入代码区域,返回代码的语言
* @command insertcode
* @method queryCommandValue
* @param { String } cmd 命令字符串
* @return { String } 返回代码的语言
* @example
* ```javascript
* editor.queryCommandValue( 'insertcode' );
* ```
*/
me.commands['insertcode'] = {
execCommand: function (cmd, lang) {
var me = this,
rng = me.selection.getRange(),
pre = domUtils.findParentByTagName(rng.startContainer, 'pre', true);
if (pre) {
pre.className = 'brush:' + lang + ';toolbar:false;';
} else {
var code = '';
if (rng.collapsed) {
code = browser.ie && browser.ie11below ? (browser.version <= 8 ? ' ' : '') : ' ';
} else {
var frag = rng.extractContents();
var div = me.document.createElement('div');
div.appendChild(frag);
utils.each(UE.filterNode(UE.htmlparser(div.innerHTML.replace(/[\r\t]/g, '')), me.options.filterTxtRules).children, function (node) {
if (browser.ie && browser.ie11below && browser.version > 8) {
if (node.type == 'element') {
if (node.tagName == 'br') {
code += '\n'
} else if (!dtd.$empty[node.tagName]) {
utils.each(node.children, function (cn) {
if (cn.type == 'element') {
if (cn.tagName == 'br') {
code += '\n'
} else if (!dtd.$empty[node.tagName]) {
code += cn.innerText();
}
} else {
code += cn.data
}
})
if (!/\n$/.test(code)) {
code += '\n';
}
}
} else {
code += node.data + '\n'
}
if (!node.nextSibling() && /\n$/.test(code)) {
code = code.replace(/\n$/, '');
}
} else {
if (browser.ie && browser.ie11below) {
if (node.type == 'element') {
if (node.tagName == 'br') {
code += ' '
} else if (!dtd.$empty[node.tagName]) {
utils.each(node.children, function (cn) {
if (cn.type == 'element') {
if (cn.tagName == 'br') {
code += ' '
} else if (!dtd.$empty[node.tagName]) {
code += cn.innerText();
}
} else {
code += cn.data
}
});
if (!/br>$/.test(code)) {
code += ' ';
}
}
} else {
code += node.data + ' '
}
if (!node.nextSibling() && / $/.test(code)) {
code = code.replace(/ $/, '');
}
} else {
code += (node.type == 'element' ? (dtd.$empty[node.tagName] ? '' : node.innerText()) : node.data);
if (!/br\/?\s*>$/.test(code)) {
if (!node.nextSibling())
return;
code += ' '
}
}
}
});
}
me.execCommand('inserthtml', '' + code + ' ', true);
pre = me.document.getElementById('coder');
domUtils.removeAttributes(pre, 'id');
var tmpNode = pre.previousSibling;
if (tmpNode && (tmpNode.nodeType == 3 && tmpNode.nodeValue.length == 1 && browser.ie && browser.version == 6 || domUtils.isEmptyBlock(tmpNode))) {
domUtils.remove(tmpNode)
}
var rng = me.selection.getRange();
if (domUtils.isEmptyBlock(pre)) {
rng.setStart(pre, 0).setCursor(false, true)
} else {
rng.selectNodeContents(pre).select()
}
}
},
queryCommandValue: function () {
var path = this.selection.getStartElementPath();
var lang = '';
utils.each(path, function (node) {
if (node.nodeName == 'PRE') {
var match = node.className.match(/brush:([^;]+)/);
lang = match && match[1] ? match[1] : '';
return false;
}
});
return lang;
}
};
me.addInputRule(function (root) {
utils.each(root.getNodesByTagName('pre'), function (pre) {
var brs = pre.getNodesByTagName('br');
if (brs.length) {
browser.ie && browser.ie11below && browser.version > 8 && utils.each(brs, function (br) {
var txt = UE.uNode.createText('\n');
br.parentNode.insertBefore(txt, br);
br.parentNode.removeChild(br);
});
return;
}
if (browser.ie && browser.ie11below && browser.version > 8)
return;
var code = pre.innerText().split(/\n/);
pre.innerHTML('');
utils.each(code, function (c) {
if (c.length) {
pre.appendChild(UE.uNode.createText(c));
}
pre.appendChild(UE.uNode.createElement('br'))
})
})
});
me.addOutputRule(function (root) {
utils.each(root.getNodesByTagName('pre'), function (pre) {
var code = '';
utils.each(pre.children, function (n) {
if (n.type == 'text') {
//在ie下文本内容有可能末尾带有\n要去掉
//trace:3396
code += n.data.replace(/[ ]/g, ' ').replace(/\n$/, '');
} else {
if (n.tagName == 'br') {
code += '\n'
} else {
code += (!dtd.$empty[n.tagName] ? '' : n.innerText());
}
}
});
pre.innerText(code.replace(/( |\n)+$/, ''))
})
});
//不需要判断highlight的command列表
me.notNeedCodeQuery = {
help: 1,
undo: 1,
redo: 1,
source: 1,
print: 1,
searchreplace: 1,
fullscreen: 1,
preview: 1,
insertparagraph: 1,
elementpath: 1,
insertcode: 1,
inserthtml: 1,
selectall: 1
};
//将queyCommamndState重置
var orgQuery = me.queryCommandState;
me.queryCommandState = function (cmd) {
var me = this;
if (!me.notNeedCodeQuery[cmd.toLowerCase()] && me.selection && me.queryCommandValue('insertcode')) {
return -1;
}
return UE.Editor.prototype.queryCommandState.apply(this, arguments)
};
me.addListener('beforeenterkeydown', function () {
var rng = me.selection.getRange();
var pre = domUtils.findParentByTagName(rng.startContainer, 'pre', true);
if (pre) {
me.fireEvent('saveScene');
if (!rng.collapsed) {
rng.deleteContents();
}
if (!browser.ie || browser.ie9above) {
var tmpNode = me.document.createElement('br'), pre;
rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true);
var next = tmpNode.nextSibling;
if (!next && (!browser.ie || browser.version > 10)) {
rng.insertNode(tmpNode.cloneNode(false));
} else {
rng.setStartAfter(tmpNode);
}
pre = tmpNode.previousSibling;
var tmp;
while (pre) {
tmp = pre;
pre = pre.previousSibling;
if (!pre || pre.nodeName == 'BR') {
pre = tmp;
break;
}
}
if (pre) {
var str = '';
while (pre && pre.nodeName != 'BR' && new RegExp('^[\\s' + domUtils.fillChar + ']*$').test(pre.nodeValue)) {
str += pre.nodeValue;
pre = pre.nextSibling;
}
if (pre.nodeName != 'BR') {
var match = pre.nodeValue.match(new RegExp('^([\\s' + domUtils.fillChar + ']+)'));
if (match && match[1]) {
str += match[1]
}
}
if (str) {
str = me.document.createTextNode(str);
rng.insertNode(str).setStartAfter(str);
}
}
rng.collapse(true).select(true);
} else {
if (browser.version > 8) {
var txt = me.document.createTextNode('\n');
var start = rng.startContainer;
if (rng.startOffset == 0) {
var preNode = start.previousSibling;
if (preNode) {
rng.insertNode(txt);
var fillchar = me.document.createTextNode(' ');
rng.setStartAfter(txt).insertNode(fillchar).setStart(fillchar, 0).collapse(true).select(true)
}
} else {
rng.insertNode(txt).setStartAfter(txt);
var fillchar = me.document.createTextNode(' ');
start = rng.startContainer.childNodes[rng.startOffset];
if (start && !/^\n/.test(start.nodeValue)) {
rng.setStartBefore(txt)
}
rng.insertNode(fillchar).setStart(fillchar, 0).collapse(true).select(true)
}
} else {
var tmpNode = me.document.createElement('br');
rng.insertNode(tmpNode);
rng.insertNode(me.document.createTextNode(domUtils.fillChar));
rng.setStartAfter(tmpNode);
pre = tmpNode.previousSibling;
var tmp;
while (pre) {
tmp = pre;
pre = pre.previousSibling;
if (!pre || pre.nodeName == 'BR') {
pre = tmp;
break;
}
}
if (pre) {
var str = '';
while (pre && pre.nodeName != 'BR' && new RegExp('^[ ' + domUtils.fillChar + ']*$').test(pre.nodeValue)) {
str += pre.nodeValue;
pre = pre.nextSibling;
}
if (pre.nodeName != 'BR') {
var match = pre.nodeValue.match(new RegExp('^([ ' + domUtils.fillChar + ']+)'));
if (match && match[1]) {
str += match[1]
}
}
str = me.document.createTextNode(str);
rng.insertNode(str).setStartAfter(str);
}
rng.collapse(true).select();
}
}
me.fireEvent('saveScene');
return true;
}
});
me.addListener('tabkeydown', function (cmd, evt) {
var rng = me.selection.getRange();
var pre = domUtils.findParentByTagName(rng.startContainer, 'pre', true);
if (pre) {
me.fireEvent('saveScene');
if (evt.shiftKey) {
} else {
if (!rng.collapsed) {
var bk = rng.createBookmark();
var start = bk.start.previousSibling;
while (start) {
if (pre.firstChild === start && !domUtils.isBr(start)) {
pre.insertBefore(me.document.createTextNode(' '), start);
break;
}
if (domUtils.isBr(start)) {
pre.insertBefore(me.document.createTextNode(' '), start.nextSibling);
break;
}
start = start.previousSibling;
}
var end = bk.end;
start = bk.start.nextSibling;
if (pre.firstChild === bk.start) {
pre.insertBefore(me.document.createTextNode(' '), start.nextSibling)
}
while (start && start !== end) {
if (domUtils.isBr(start) && start.nextSibling) {
if (start.nextSibling === end) {
break;
}
pre.insertBefore(me.document.createTextNode(' '), start.nextSibling)
}
start = start.nextSibling;
}
rng.moveToBookmark(bk).select();
} else {
var tmpNode = me.document.createTextNode(' ');
rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true).select(true);
}
}
me.fireEvent('saveScene');
return true;
}
});
me.addListener('beforeinserthtml', function (evtName, html) {
var me = this,
rng = me.selection.getRange(),
pre = domUtils.findParentByTagName(rng.startContainer, 'pre', true);
if (pre) {
if (!rng.collapsed) {
rng.deleteContents()
}
var htmlstr = '';
if (browser.ie && browser.version > 8) {
utils.each(UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules).children, function (node) {
if (node.type == 'element') {
if (node.tagName == 'br') {
htmlstr += '\n'
} else if (!dtd.$empty[node.tagName]) {
utils.each(node.children, function (cn) {
if (cn.type == 'element') {
if (cn.tagName == 'br') {
htmlstr += '\n'
} else if (!dtd.$empty[node.tagName]) {
htmlstr += cn.innerText();
}
} else {
htmlstr += cn.data
}
})
if (!/\n$/.test(htmlstr)) {
htmlstr += '\n';
}
}
} else {
htmlstr += node.data + '\n'
}
if (!node.nextSibling() && /\n$/.test(htmlstr)) {
htmlstr = htmlstr.replace(/\n$/, '');
}
});
var tmpNode = me.document.createTextNode(utils.html(htmlstr.replace(/ /g, ' ')));
rng.insertNode(tmpNode).selectNode(tmpNode).select();
} else {
var frag = me.document.createDocumentFragment();
utils.each(UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules).children, function (node) {
if (node.type == 'element') {
if (node.tagName == 'br') {
frag.appendChild(me.document.createElement('br'))
} else if (!dtd.$empty[node.tagName]) {
utils.each(node.children, function (cn) {
if (cn.type == 'element') {
if (cn.tagName == 'br') {
frag.appendChild(me.document.createElement('br'))
} else if (!dtd.$empty[node.tagName]) {
frag.appendChild(me.document.createTextNode(utils.html(cn.innerText().replace(/ /g, ' '))));
}
} else {
frag.appendChild(me.document.createTextNode(utils.html(cn.data.replace(/ /g, ' '))));
}
})
if (frag.lastChild.nodeName != 'BR') {
frag.appendChild(me.document.createElement('br'))
}
}
} else {
frag.appendChild(me.document.createTextNode(utils.html(node.data.replace(/ /g, ' '))));
}
if (!node.nextSibling() && frag.lastChild.nodeName == 'BR') {
frag.removeChild(frag.lastChild)
}
});
rng.insertNode(frag).select();
}
return true;
}
});
//方向键的处理
me.addListener('keydown', function (cmd, evt) {
var me = this, keyCode = evt.keyCode || evt.which;
if (keyCode == 40) {
var rng = me.selection.getRange(), pre, start = rng.startContainer;
if (rng.collapsed && (pre = domUtils.findParentByTagName(rng.startContainer, 'pre', true)) && !pre.nextSibling) {
var last = pre.lastChild
while (last && last.nodeName == 'BR') {
last = last.previousSibling;
}
if (last === start || rng.startContainer === pre && rng.startOffset == pre.childNodes.length) {
me.execCommand('insertparagraph');
domUtils.preventDefault(evt)
}
}
}
});
//trace:3395
me.addListener('delkeydown', function (type, evt) {
var rng = this.selection.getRange();
rng.txtToElmBoundary(true);
var start = rng.startContainer;
if (domUtils.isTagNode(start, 'pre') && rng.collapsed && domUtils.isStartInblock(rng)) {
var p = me.document.createElement('p');
domUtils.fillNode(me.document, p);
start.parentNode.insertBefore(p, start);
domUtils.remove(start);
rng.setStart(p, 0).setCursor(false, true);
domUtils.preventDefault(evt);
return true;
}
})
};
// plugins/cleardoc.js
/**
* 清空文档插件
* @file
* @since 1.2.6.1
*/
/**
* 清空文档
* @command cleardoc
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* //editor 是编辑器实例
* editor.execCommand('cleardoc');
* ```
*/
UE.commands['cleardoc'] = {
execCommand: function (cmdName) {
var me = this,
enterTag = me.options.enterTag,
range = me.selection.getRange();
if (enterTag == "br") {
me.body.innerHTML = " ";
range.setStart(me.body, 0).setCursor();
} else {
me.body.innerHTML = "" + (ie ? "" : " ") + "
";
range.setStart(me.body.firstChild, 0).setCursor(false, true);
}
setTimeout(function () {
me.fireEvent("clearDoc");
}, 0);
}
};
// plugins/anchor.js
/**
* 锚点插件,为UEditor提供插入锚点支持
* @file
* @since 1.2.6.1
*/
UE.plugin.register('anchor', function () {
return {
bindEvents: {
'ready': function () {
utils.cssRule('anchor',
'.anchorclass{background: url(\''
+ this.options.themePath
+ this.options.theme + '/images/anchor.gif\') no-repeat scroll left center transparent;cursor: auto;display: inline-block;height: 16px;width: 15px;}',
this.document);
}
},
outputRule: function (root) {
utils.each(root.getNodesByTagName('img'), function (a) {
var val;
if (val = a.getAttr('anchorname')) {
a.tagName = 'a';
a.setAttr({
anchorname: '',
name: val,
'class': ''
})
}
})
},
inputRule: function (root) {
utils.each(root.getNodesByTagName('a'), function (a) {
var val;
if ((val = a.getAttr('name')) && !a.getAttr('href')) {
a.tagName = 'img';
a.setAttr({
anchorname: a.getAttr('name'),
'class': 'anchorclass'
});
a.setAttr('name')
}
})
},
commands: {
/**
* 插入锚点
* @command anchor
* @method execCommand
* @param { String } cmd 命令字符串
* @param { String } name 锚点名称字符串
* @example
* ```javascript
* //editor 是编辑器实例
* editor.execCommand('anchor', 'anchor1');
* ```
*/
'anchor': {
execCommand: function (cmd, name) {
var range = this.selection.getRange(), img = range.getClosedNode();
if (img && img.getAttribute('anchorname')) {
if (name) {
img.setAttribute('anchorname', name);
} else {
range.setStartBefore(img).setCursor();
domUtils.remove(img);
}
} else {
if (name) {
//只在选区的开始插入
var anchor = this.document.createElement('img');
range.collapse(true);
domUtils.setAttributes(anchor, {
'anchorname': name,
'class': 'anchorclass'
});
range.insertNode(anchor).setStartAfter(anchor).setCursor(false, true);
}
}
}
}
}
}
});
// plugins/wordcount.js
///import core
///commands 字数统计
///commandsName WordCount,wordCount
///commandsTitle 字数统计
/*
* Created by JetBrains WebStorm.
* User: taoqili
* Date: 11-9-7
* Time: 下午8:18
* To change this template use File | Settings | File Templates.
*/
UE.plugins['wordcount'] = function () {
var me = this;
me.setOpt('wordCount', true);
me.addListener('contentchange', function () {
me.fireEvent('wordcount');
});
var timer;
me.addListener('ready', function () {
var me = this;
domUtils.on(me.body, "keyup", function (evt) {
var code = evt.keyCode || evt.which,
//忽略的按键,ctr,alt,shift,方向键
ignores = { "16": 1, "18": 1, "20": 1, "37": 1, "38": 1, "39": 1, "40": 1 };
if (code in ignores) return;
clearTimeout(timer);
timer = setTimeout(function () {
me.fireEvent('wordcount');
}, 200)
})
});
};
// plugins/pagebreak.js
/**
* 分页功能插件
* @file
* @since 1.2.6.1
*/
UE.plugins['pagebreak'] = function () {
var me = this,
notBreakTags = ['td'];
me.setOpt('pageBreakTag', '_ueditor_page_break_tag_');
function fillNode(node) {
if (domUtils.isEmptyBlock(node)) {
var firstChild = node.firstChild, tmpNode;
while (firstChild && firstChild.nodeType == 1 && domUtils.isEmptyBlock(firstChild)) {
tmpNode = firstChild;
firstChild = firstChild.firstChild;
}
!tmpNode && (tmpNode = node);
domUtils.fillNode(me.document, tmpNode);
}
}
//分页符样式添加
me.ready(function () {
utils.cssRule('pagebreak', '.pagebreak{display:block;clear:both !important;cursor:default !important;width: 100% !important;margin:0;}', me.document);
});
function isHr(node) {
return node && node.nodeType == 1 && node.tagName == 'HR' && node.className == 'pagebreak';
}
me.addInputRule(function (root) {
root.traversal(function (node) {
if (node.type == 'text' && node.data == me.options.pageBreakTag) {
var hr = UE.uNode.createElement(' ');
node.parentNode.insertBefore(hr, node);
node.parentNode.removeChild(node)
}
})
});
me.addOutputRule(function (node) {
utils.each(node.getNodesByTagName('hr'), function (n) {
if (n.getAttr('class') == 'pagebreak') {
var txt = UE.uNode.createText(me.options.pageBreakTag);
n.parentNode.insertBefore(txt, n);
n.parentNode.removeChild(n);
}
})
});
/**
* 插入分页符
* @command pagebreak
* @method execCommand
* @param { String } cmd 命令字符串
* @remind 在表格中插入分页符会把表格切分成两部分
* @remind 获取编辑器内的数据时, 编辑器会把分页符转换成“_ueditor_page_break_tag_”字符串,
* 以便于提交数据到服务器端后处理分页。
* @example
* ```javascript
* editor.execCommand( 'pagebreak'); //插入一个hr标签,带有样式类名pagebreak
* ```
*/
me.commands['pagebreak'] = {
execCommand: function () {
var range = me.selection.getRange(), hr = me.document.createElement('hr');
domUtils.setAttributes(hr, {
'class': 'pagebreak',
noshade: "noshade",
size: "5"
});
domUtils.unSelectable(hr);
//table单独处理
var node = domUtils.findParentByTagName(range.startContainer, notBreakTags, true),
parents = [], pN;
if (node) {
switch (node.tagName) {
case 'TD':
pN = node.parentNode;
if (!pN.previousSibling) {
var table = domUtils.findParentByTagName(pN, 'table');
// var tableWrapDiv = table.parentNode;
// if(tableWrapDiv && tableWrapDiv.nodeType == 1
// && tableWrapDiv.tagName == 'DIV'
// && tableWrapDiv.getAttribute('dropdrag')
// ){
// domUtils.remove(tableWrapDiv,true);
// }
table.parentNode.insertBefore(hr, table);
parents = domUtils.findParents(hr, true);
} else {
pN.parentNode.insertBefore(hr, pN);
parents = domUtils.findParents(hr);
}
pN = parents[1];
if (hr !== pN) {
domUtils.breakParent(hr, pN);
}
//table要重写绑定一下拖拽
me.fireEvent('afteradjusttable', me.document);
}
} else {
if (!range.collapsed) {
range.deleteContents();
var start = range.startContainer;
while (!domUtils.isBody(start) && domUtils.isBlockElm(start) && domUtils.isEmptyNode(start)) {
range.setStartBefore(start).collapse(true);
domUtils.remove(start);
start = range.startContainer;
}
}
range.insertNode(hr);
var pN = hr.parentNode, nextNode;
while (!domUtils.isBody(pN)) {
domUtils.breakParent(hr, pN);
nextNode = hr.nextSibling;
if (nextNode && domUtils.isEmptyBlock(nextNode)) {
domUtils.remove(nextNode);
}
pN = hr.parentNode;
}
nextNode = hr.nextSibling;
var pre = hr.previousSibling;
if (isHr(pre)) {
domUtils.remove(pre);
} else {
pre && fillNode(pre);
}
if (!nextNode) {
var p = me.document.createElement('p');
hr.parentNode.appendChild(p);
domUtils.fillNode(me.document, p);
range.setStart(p, 0).collapse(true);
} else {
if (isHr(nextNode)) {
domUtils.remove(nextNode);
} else {
fillNode(nextNode);
}
range.setEndAfter(hr).collapse(false);
}
range.select(true);
}
}
};
};
// plugins/wordimage.js
///import core
///commands 本地图片引导上传
///commandsName WordImage
///commandsTitle 本地图片引导上传
///commandsDialog dialogs\wordimage
UE.plugin.register('wordimage', function () {
var me = this,
images = [];
return {
commands: {
'wordimage': {
execCommand: function () {
var images = domUtils.getElementsByTagName(me.body, "img");
var urlList = [];
for (var i = 0, ci; ci = images[i++];) {
var url = ci.getAttribute("word_img");
url && urlList.push(url);
}
return urlList;
},
queryCommandState: function () {
images = domUtils.getElementsByTagName(me.body, "img");
for (var i = 0, ci; ci = images[i++];) {
if (ci.getAttribute("word_img")) {
return 1;
}
}
return -1;
},
notNeedUndo: true
}
},
inputRule: function (root) {
utils.each(root.getNodesByTagName('img'), function (img) {
var attrs = img.attrs,
flag = parseInt(attrs.width) < 128 || parseInt(attrs.height) < 43,
opt = me.options,
src = opt.UEDITOR_HOME_URL + 'themes/default/images/spacer.gif';
if (attrs['src'] && /^(?:(file:\/+))/.test(attrs['src'])) {
img.setAttr({
width: attrs.width,
height: attrs.height,
alt: attrs.alt,
word_img: attrs.src,
src: src,
'style': 'background:url(' + (flag ? opt.themePath + opt.theme + '/images/word.gif' : opt.langPath + opt.lang + '/images/localimage.png') + ') no-repeat center center;border:1px solid #ddd'
})
}
})
}
}
});
// plugins/dragdrop.js
UE.plugins['dragdrop'] = function () {
var me = this;
me.ready(function () {
domUtils.on(this.body, 'dragend', function () {
var rng = me.selection.getRange();
var node = rng.getClosedNode() || me.selection.getStart();
if (node && node.tagName == 'IMG') {
var pre = node.previousSibling, next;
while (next = node.nextSibling) {
if (next.nodeType == 1 && next.tagName == 'SPAN' && !next.firstChild) {
domUtils.remove(next)
} else {
break;
}
}
if ((pre && pre.nodeType == 1 && !domUtils.isEmptyBlock(pre) || !pre) && (!next || next && !domUtils.isEmptyBlock(next))) {
if (pre && pre.tagName == 'P' && !domUtils.isEmptyBlock(pre)) {
pre.appendChild(node);
domUtils.moveChild(next, pre);
domUtils.remove(next);
} else if (next && next.tagName == 'P' && !domUtils.isEmptyBlock(next)) {
next.insertBefore(node, next.firstChild);
}
if (pre && pre.tagName == 'P' && domUtils.isEmptyBlock(pre)) {
domUtils.remove(pre)
}
if (next && next.tagName == 'P' && domUtils.isEmptyBlock(next)) {
domUtils.remove(next)
}
rng.selectNode(node).select();
me.fireEvent('saveScene');
}
}
})
});
me.addListener('keyup', function (type, evt) {
var keyCode = evt.keyCode || evt.which;
if (keyCode == 13) {
var rng = me.selection.getRange(), node;
if (node = domUtils.findParentByTagName(rng.startContainer, 'p', true)) {
if (domUtils.getComputedStyle(node, 'text-align') == 'center') {
domUtils.removeStyle(node, 'text-align')
}
}
}
})
};
// plugins/undo.js
/**
* undo redo
* @file
* @since 1.2.6.1
*/
/**
* 撤销上一次执行的命令
* @command undo
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'undo' );
* ```
*/
/**
* 重做上一次执行的命令
* @command redo
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'redo' );
* ```
*/
UE.plugins['undo'] = function () {
var saveSceneTimer;
var me = this,
maxUndoCount = me.options.maxUndoCount || 20,
maxInputCount = me.options.maxInputCount || 20,
fillchar = new RegExp(domUtils.fillChar + '|<\/hr>', 'gi');// ie会产生多余的
var noNeedFillCharTags = {
ol: 1, ul: 1, table: 1, tbody: 1, tr: 1, body: 1
};
var orgState = me.options.autoClearEmptyNode;
function compareAddr(indexA, indexB) {
if (indexA.length != indexB.length)
return 0;
for (var i = 0, l = indexA.length; i < l; i++) {
if (indexA[i] != indexB[i])
return 0
}
return 1;
}
function compareRangeAddress(rngAddrA, rngAddrB) {
if (rngAddrA.collapsed != rngAddrB.collapsed) {
return 0;
}
if (!compareAddr(rngAddrA.startAddress, rngAddrB.startAddress) || !compareAddr(rngAddrA.endAddress, rngAddrB.endAddress)) {
return 0;
}
return 1;
}
function UndoManager() {
this.list = [];
this.index = 0;
this.hasUndo = false;
this.hasRedo = false;
this.undo = function () {
if (this.hasUndo) {
if (!this.list[this.index - 1] && this.list.length == 1) {
this.reset();
return;
}
while (this.list[this.index].content == this.list[this.index - 1].content) {
this.index--;
if (this.index == 0) {
return this.restore(0);
}
}
this.restore(--this.index);
}
};
this.redo = function () {
if (this.hasRedo) {
while (this.list[this.index].content == this.list[this.index + 1].content) {
this.index++;
if (this.index == this.list.length - 1) {
return this.restore(this.index);
}
}
this.restore(++this.index);
}
};
this.restore = function () {
var me = this.editor;
var scene = this.list[this.index];
var root = UE.htmlparser(scene.content.replace(fillchar, ''));
me.options.autoClearEmptyNode = false;
me.filterInputRule(root);
me.options.autoClearEmptyNode = orgState;
//trace:873
//去掉展位符
me.document.body.innerHTML = root.toHtml();
me.fireEvent('afterscencerestore');
//处理undo后空格不展位的问题
if (browser.ie) {
utils.each(domUtils.getElementsByTagName(me.document, 'td th caption p'), function (node) {
if (domUtils.isEmptyNode(node)) {
domUtils.fillNode(me.document, node);
}
})
}
try {
var rng = new dom.Range(me.document).moveToAddress(scene.address);
rng.select(noNeedFillCharTags[rng.startContainer.nodeName.toLowerCase()]);
} catch (e) { }
this.update();
this.clearKey();
//不能把自己reset了
me.fireEvent('reset', true);
};
this.getScene = function () {
var me = this.editor;
var rng = me.selection.getRange(),
rngAddress = rng.createAddress(false, true);
me.fireEvent('beforegetscene');
var root = UE.htmlparser(me.body.innerHTML);
me.options.autoClearEmptyNode = false;
me.filterOutputRule(root);
me.options.autoClearEmptyNode = orgState;
var cont = root.toHtml();
//trace:3461
//这个会引起回退时导致空格丢失的情况
// browser.ie && (cont = cont.replace(/> <').replace(/\s*\s*/g, '>'));
me.fireEvent('aftergetscene');
return {
address: rngAddress,
content: cont
}
};
this.save = function (notCompareRange, notSetCursor) {
clearTimeout(saveSceneTimer);
var currentScene = this.getScene(notSetCursor),
lastScene = this.list[this.index];
if (lastScene && lastScene.content != currentScene.content) {
me.trigger('contentchange')
}
//内容相同位置相同不存
if (lastScene && lastScene.content == currentScene.content &&
(notCompareRange ? 1 : compareRangeAddress(lastScene.address, currentScene.address))
) {
return;
}
this.list = this.list.slice(0, this.index + 1);
this.list.push(currentScene);
//如果大于最大数量了,就把最前的剔除
if (this.list.length > maxUndoCount) {
this.list.shift();
}
this.index = this.list.length - 1;
this.clearKey();
//跟新undo/redo状态
this.update();
};
this.update = function () {
this.hasRedo = !!this.list[this.index + 1];
this.hasUndo = !!this.list[this.index - 1];
};
this.reset = function () {
this.list = [];
this.index = 0;
this.hasUndo = false;
this.hasRedo = false;
this.clearKey();
};
this.clearKey = function () {
keycont = 0;
lastKeyCode = null;
};
}
me.undoManger = new UndoManager();
me.undoManger.editor = me;
function saveScene() {
this.undoManger.save();
}
me.addListener('saveScene', function () {
var args = Array.prototype.splice.call(arguments, 1);
this.undoManger.save.apply(this.undoManger, args);
});
// me.addListener('beforeexeccommand', saveScene);
// me.addListener('afterexeccommand', saveScene);
me.addListener('reset', function (type, exclude) {
if (!exclude) {
this.undoManger.reset();
}
});
me.commands['redo'] = me.commands['undo'] = {
execCommand: function (cmdName) {
this.undoManger[cmdName]();
},
queryCommandState: function (cmdName) {
return this.undoManger['has' + (cmdName.toLowerCase() == 'undo' ? 'Undo' : 'Redo')] ? 0 : -1;
},
notNeedUndo: 1
};
var keys = {
// /*Backspace*/ 8:1, /*Delete*/ 46:1,
/*Shift*/ 16: 1, /*Ctrl*/ 17: 1, /*Alt*/ 18: 1,
37: 1, 38: 1, 39: 1, 40: 1
},
keycont = 0,
lastKeyCode;
//输入法状态下不计算字符数
var inputType = false;
me.addListener('ready', function () {
domUtils.on(this.body, 'compositionstart', function () {
inputType = true;
});
domUtils.on(this.body, 'compositionend', function () {
inputType = false;
})
});
//快捷键
me.addshortcutkey({
"Undo": "ctrl+90", //undo
"Redo": "ctrl+89" //redo
});
var isCollapsed = true;
me.addListener('keydown', function (type, evt) {
var me = this;
var keyCode = evt.keyCode || evt.which;
if (!keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
if (inputType)
return;
if (!me.selection.getRange().collapsed) {
me.undoManger.save(false, true);
isCollapsed = false;
return;
}
if (me.undoManger.list.length == 0) {
me.undoManger.save(true);
}
clearTimeout(saveSceneTimer);
function save(cont) {
cont.undoManger.save(false, true);
cont.fireEvent('selectionchange');
}
saveSceneTimer = setTimeout(function () {
if (inputType) {
var interalTimer = setInterval(function () {
if (!inputType) {
save(me);
clearInterval(interalTimer)
}
}, 300)
return;
}
save(me);
}, 200);
lastKeyCode = keyCode;
keycont++;
if (keycont >= maxInputCount) {
save(me)
}
}
});
me.addListener('keyup', function (type, evt) {
var keyCode = evt.keyCode || evt.which;
if (!keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
if (inputType)
return;
if (!isCollapsed) {
this.undoManger.save(false, true);
isCollapsed = true;
}
}
});
//扩展实例,添加关闭和开启命令undo
me.stopCmdUndo = function () {
me.__hasEnterExecCommand = true;
};
me.startCmdUndo = function () {
me.__hasEnterExecCommand = false;
}
};
// plugins/copy.js
UE.plugin.register('copy', function () {
var me = this;
function initZeroClipboard() {
ZeroClipboard.config({
debug: false,
swfPath: me.options.UEDITOR_HOME_URL + 'third-party/zeroclipboard/ZeroClipboard.swf'
});
var client = me.zeroclipboard = new ZeroClipboard();
// 复制内容
client.on('copy', function (e) {
var client = e.client,
rng = me.selection.getRange(),
div = document.createElement('div');
div.appendChild(rng.cloneContents());
client.setText(div.innerText || div.textContent);
client.setHtml(div.innerHTML);
rng.select();
});
// hover事件传递到target
client.on('mouseover mouseout', function (e) {
var target = e.target;
if (e.type == 'mouseover') {
domUtils.addClass(target, 'edui-state-hover');
} else if (e.type == 'mouseout') {
domUtils.removeClasses(target, 'edui-state-hover');
}
});
// flash加载不成功
client.on('wrongflash noflash', function () {
ZeroClipboard.destroy();
});
}
return {
bindEvents: {
'ready': function () {
if (!browser.ie) {
if (window.ZeroClipboard) {
initZeroClipboard();
} else {
utils.loadFile(document, {
src: me.options.UEDITOR_HOME_URL + "third-party/zeroclipboard/ZeroClipboard.js",
tag: "script",
type: "text/javascript",
defer: "defer"
}, function () {
initZeroClipboard();
});
}
}
}
},
commands: {
'copy': {
execCommand: function (cmd) {
if (!me.document.execCommand('copy')) {
alert(me.getLang('copymsg'));
}
}
}
}
}
});
// plugins/paste.js
///import core
///import plugins/inserthtml.js
///import plugins/undo.js
///import plugins/serialize.js
///commands 粘贴
///commandsName PastePlain
///commandsTitle 纯文本粘贴模式
/**
* @description 粘贴
* @author zhanyi
*/
UE.plugins['paste'] = function () {
function getClipboardData(callback) {
var doc = this.document;
if (doc.getElementById('baidu_pastebin')) {
return;
}
var range = this.selection.getRange(),
bk = range.createBookmark(),
//创建剪贴的容器div
pastebin = doc.createElement('div');
pastebin.id = 'baidu_pastebin';
// Safari 要求div必须有内容,才能粘贴内容进来
browser.webkit && pastebin.appendChild(doc.createTextNode(domUtils.fillChar + domUtils.fillChar));
doc.body.appendChild(pastebin);
//trace:717 隐藏的span不能得到top
//bk.start.innerHTML = ' ';
bk.start.style.display = '';
pastebin.style.cssText = "position:absolute;width:1px;height:1px;overflow:hidden;left:-1000px;white-space:nowrap;top:" +
//要在现在光标平行的位置加入,否则会出现跳动的问题
domUtils.getXY(bk.start).y + 'px';
range.selectNodeContents(pastebin).select(true);
setTimeout(function () {
if (browser.webkit) {
for (var i = 0, pastebins = doc.querySelectorAll('#baidu_pastebin'), pi; pi = pastebins[i++];) {
if (domUtils.isEmptyNode(pi)) {
domUtils.remove(pi);
} else {
pastebin = pi;
break;
}
}
}
try {
pastebin.parentNode.removeChild(pastebin);
} catch (e) {
}
range.moveToBookmark(bk).select(true);
callback(pastebin);
}, 0);
}
var me = this;
me.setOpt({
retainOnlyLabelPasted: false
});
var txtContent, htmlContent, address;
function getPureHtml(html) {
return html.replace(/<(\/?)([\w\-]+)([^>]*)>/gi, function (a, b, tagName, attrs) {
tagName = tagName.toLowerCase();
if ({ img: 1 }[tagName]) {
return a;
}
attrs = attrs.replace(/([\w\-]*?)\s*=\s*(("([^"]*)")|('([^']*)')|([^\s>]+))/gi, function (str, atr, val) {
if ({
'src': 1,
'href': 1,
'name': 1
}[atr.toLowerCase()]) {
return atr + '=' + val + ' '
}
return ''
});
if ({
'span': 1,
'div': 1
}[tagName]) {
return ''
} else {
return '<' + b + tagName + ' ' + utils.trim(attrs) + '>'
}
});
}
function filter(div) {
var html;
if (div.firstChild) {
//去掉cut中添加的边界值
var nodes = domUtils.getElementsByTagName(div, 'span');
for (var i = 0, ni; ni = nodes[i++];) {
if (ni.id == '_baidu_cut_start' || ni.id == '_baidu_cut_end') {
domUtils.remove(ni);
}
}
if (browser.webkit) {
var brs = div.querySelectorAll('div br');
for (var i = 0, bi; bi = brs[i++];) {
var pN = bi.parentNode;
if (pN.tagName == 'DIV' && pN.childNodes.length == 1) {
pN.innerHTML = '
';
domUtils.remove(pN);
}
}
var divs = div.querySelectorAll('#baidu_pastebin');
for (var i = 0, di; di = divs[i++];) {
var tmpP = me.document.createElement('p');
di.parentNode.insertBefore(tmpP, di);
while (di.firstChild) {
tmpP.appendChild(di.firstChild);
}
domUtils.remove(di);
}
var metas = div.querySelectorAll('meta');
for (var i = 0, ci; ci = metas[i++];) {
domUtils.remove(ci);
}
var brs = div.querySelectorAll('br');
for (i = 0; ci = brs[i++];) {
if (/^apple-/i.test(ci.className)) {
domUtils.remove(ci);
}
}
}
if (browser.gecko) {
var dirtyNodes = div.querySelectorAll('[_moz_dirty]');
for (i = 0; ci = dirtyNodes[i++];) {
ci.removeAttribute('_moz_dirty');
}
}
if (!browser.ie) {
var spans = div.querySelectorAll('span.Apple-style-span');
for (var i = 0, ci; ci = spans[i++];) {
domUtils.remove(ci, true);
}
}
//ie下使用innerHTML会产生多余的\r\n字符,也会产生 这里过滤掉
html = div.innerHTML;//.replace(/>(?:(\s| )*?)<');
//过滤word粘贴过来的冗余属性
html = UE.filterWord(html);
//取消了忽略空白的第二个参数,粘贴过来的有些是有空白的,会被套上相关的标签
var root = UE.htmlparser(html);
//如果给了过滤规则就先进行过滤
if (me.options.filterRules) {
UE.filterNode(root, me.options.filterRules);
}
//执行默认的处理
me.filterInputRule(root);
//针对chrome的处理
if (browser.webkit) {
var br = root.lastChild();
if (br && br.type == 'element' && br.tagName == 'br') {
root.removeChild(br)
}
utils.each(me.body.querySelectorAll('div'), function (node) {
if (domUtils.isEmptyBlock(node)) {
domUtils.remove(node, true)
}
})
}
html = { 'html': root.toHtml() };
me.fireEvent('beforepaste', html, root);
//抢了默认的粘贴,那后边的内容就不执行了,比如表格粘贴
if (!html.html) {
return;
}
root = UE.htmlparser(html.html, true);
//如果开启了纯文本模式
if (me.queryCommandState('pasteplain') === 1) {
me.execCommand('insertHtml', UE.filterNode(root, me.options.filterTxtRules).toHtml(), true);
} else {
//文本模式
UE.filterNode(root, me.options.filterTxtRules);
txtContent = root.toHtml();
//完全模式
htmlContent = html.html;
address = me.selection.getRange().createAddress(true);
me.execCommand('insertHtml', me.getOpt('retainOnlyLabelPasted') === true ? getPureHtml(htmlContent) : htmlContent, true);
}
me.fireEvent("afterpaste", html);
}
}
me.addListener('pasteTransfer', function (cmd, plainType) {
if (address && txtContent && htmlContent && txtContent != htmlContent) {
var range = me.selection.getRange();
range.moveToAddress(address, true);
if (!range.collapsed) {
while (!domUtils.isBody(range.startContainer)
) {
var start = range.startContainer;
if (start.nodeType == 1) {
start = start.childNodes[range.startOffset];
if (!start) {
range.setStartBefore(range.startContainer);
continue;
}
var pre = start.previousSibling;
if (pre && pre.nodeType == 3 && new RegExp('^[\n\r\t ' + domUtils.fillChar + ']*$').test(pre.nodeValue)) {
range.setStartBefore(pre)
}
}
if (range.startOffset == 0) {
range.setStartBefore(range.startContainer);
} else {
break;
}
}
while (!domUtils.isBody(range.endContainer)
) {
var end = range.endContainer;
if (end.nodeType == 1) {
end = end.childNodes[range.endOffset];
if (!end) {
range.setEndAfter(range.endContainer);
continue;
}
var next = end.nextSibling;
if (next && next.nodeType == 3 && new RegExp('^[\n\r\t' + domUtils.fillChar + ']*$').test(next.nodeValue)) {
range.setEndAfter(next)
}
}
if (range.endOffset == range.endContainer[range.endContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length) {
range.setEndAfter(range.endContainer);
} else {
break;
}
}
}
range.deleteContents();
range.select(true);
me.__hasEnterExecCommand = true;
var html = htmlContent;
if (plainType === 2) {
html = getPureHtml(html);
} else if (plainType) {
html = txtContent;
}
me.execCommand('inserthtml', html, true);
me.__hasEnterExecCommand = false;
var rng = me.selection.getRange();
while (!domUtils.isBody(rng.startContainer) && !rng.startOffset &&
rng.startContainer[rng.startContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length
) {
rng.setStartBefore(rng.startContainer);
}
var tmpAddress = rng.createAddress(true);
address.endAddress = tmpAddress.startAddress;
}
});
me.addListener('ready', function () {
domUtils.on(me.body, 'cut', function () {
var range = me.selection.getRange();
if (!range.collapsed && me.undoManger) {
me.undoManger.save();
}
});
//ie下beforepaste在点击右键时也会触发,所以用监控键盘才处理
domUtils.on(me.body, browser.ie || browser.opera ? 'keydown' : 'paste', function (e) {
if ((browser.ie || browser.opera) && ((!e.ctrlKey && !e.metaKey) || e.keyCode != '86')) {
return;
}
getClipboardData.call(me, function (div) {
filter(div);
});
});
});
me.commands['paste'] = {
execCommand: function (cmd) {
if (browser.ie) {
getClipboardData.call(me, function (div) {
filter(div);
});
me.document.execCommand('paste');
} else {
alert(me.getLang('pastemsg'));
}
}
}
};
// plugins/puretxtpaste.js
/**
* 纯文本粘贴插件
* @file
* @since 1.2.6.1
*/
UE.plugins['pasteplain'] = function () {
var me = this;
me.setOpt({
'pasteplain': false,
'filterTxtRules': function () {
function transP(node) {
node.tagName = 'p';
node.setStyle();
}
function removeNode(node) {
node.parentNode.removeChild(node, true)
}
return {
//直接删除及其字节点内容
'-': 'script style object iframe embed input select',
'p': { $: {} },
'br': { $: {} },
div: function (node) {
var tmpNode, p = UE.uNode.createElement('p');
while (tmpNode = node.firstChild()) {
if (tmpNode.type == 'text' || !UE.dom.dtd.$block[tmpNode.tagName]) {
p.appendChild(tmpNode);
} else {
if (p.firstChild()) {
node.parentNode.insertBefore(p, node);
p = UE.uNode.createElement('p');
} else {
node.parentNode.insertBefore(tmpNode, node);
}
}
}
if (p.firstChild()) {
node.parentNode.insertBefore(p, node);
}
node.parentNode.removeChild(node);
},
ol: removeNode,
ul: removeNode,
dl: removeNode,
dt: removeNode,
dd: removeNode,
'li': removeNode,
'caption': transP,
'th': transP,
'tr': transP,
'h1': transP, 'h2': transP, 'h3': transP, 'h4': transP, 'h5': transP, 'h6': transP,
'td': function (node) {
//没有内容的td直接删掉
var txt = !!node.innerText();
if (txt) {
node.parentNode.insertAfter(UE.uNode.createText(' '), node);
}
node.parentNode.removeChild(node, node.innerText())
}
}
}()
});
//暂时这里支持一下老版本的属性
var pasteplain = me.options.pasteplain;
/**
* 启用或取消纯文本粘贴模式
* @command pasteplain
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.queryCommandState( 'pasteplain' );
* ```
*/
/**
* 查询当前是否处于纯文本粘贴模式
* @command pasteplain
* @method queryCommandState
* @param { String } cmd 命令字符串
* @return { int } 如果处于纯文本模式,返回1,否则,返回0
* @example
* ```javascript
* editor.queryCommandState( 'pasteplain' );
* ```
*/
me.commands['pasteplain'] = {
queryCommandState: function () {
return pasteplain ? 1 : 0;
},
execCommand: function () {
pasteplain = !pasteplain | 0;
},
notNeedUndo: 1
};
};
// plugins/list.js
/**
* 有序列表,无序列表插件
* @file
* @since 1.2.6.1
*/
UE.plugins['list'] = function () {
var me = this,
notExchange = {
'TD': 1,
'PRE': 1,
'BLOCKQUOTE': 1
};
var customStyle = {
'cn': 'cn-1-',
'cn1': 'cn-2-',
'cn2': 'cn-3-',
'num': 'num-1-',
'num1': 'num-2-',
'num2': 'num-3-',
'dash': 'dash',
'dot': 'dot'
};
me.setOpt({
'autoTransWordToList': false,
'insertorderedlist': {
'num': '',
'num1': '',
'num2': '',
'cn': '',
'cn1': '',
'cn2': '',
'decimal': '',
'lower-alpha': '',
'lower-roman': '',
'upper-alpha': '',
'upper-roman': ''
},
'insertunorderedlist': {
'circle': '',
'disc': '',
'square': '',
'dash': '',
'dot': ''
},
listDefaultPaddingLeft: '30',
listiconpath: 'http://bs.baidu.com/listicon/',
maxListLevel: -1,//-1不限制
disablePInList: false
});
function listToArray(list) {
var arr = [];
for (var p in list) {
arr.push(p)
}
return arr;
}
var listStyle = {
'OL': listToArray(me.options.insertorderedlist),
'UL': listToArray(me.options.insertunorderedlist)
};
var liiconpath = me.options.listiconpath;
//根据用户配置,调整customStyle
for (var s in customStyle) {
if (!me.options.insertorderedlist.hasOwnProperty(s) && !me.options.insertunorderedlist.hasOwnProperty(s)) {
delete customStyle[s];
}
}
me.ready(function () {
var customCss = [];
for (var p in customStyle) {
if (p == 'dash' || p == 'dot') {
customCss.push('li.list-' + customStyle[p] + '{background-image:url(' + liiconpath + customStyle[p] + '.gif)}');
customCss.push('ul.custom_' + p + '{list-style:none;}ul.custom_' + p + ' li{background-position:0 3px;background-repeat:no-repeat}');
} else {
for (var i = 0; i < 99; i++) {
customCss.push('li.list-' + customStyle[p] + i + '{background-image:url(' + liiconpath + 'list-' + customStyle[p] + i + '.gif)}')
}
customCss.push('ol.custom_' + p + '{list-style:none;}ol.custom_' + p + ' li{background-position:0 3px;background-repeat:no-repeat}');
}
switch (p) {
case 'cn':
customCss.push('li.list-' + p + '-paddingleft-1{padding-left:25px}');
customCss.push('li.list-' + p + '-paddingleft-2{padding-left:40px}');
customCss.push('li.list-' + p + '-paddingleft-3{padding-left:55px}');
break;
case 'cn1':
customCss.push('li.list-' + p + '-paddingleft-1{padding-left:30px}');
customCss.push('li.list-' + p + '-paddingleft-2{padding-left:40px}');
customCss.push('li.list-' + p + '-paddingleft-3{padding-left:55px}');
break;
case 'cn2':
customCss.push('li.list-' + p + '-paddingleft-1{padding-left:40px}');
customCss.push('li.list-' + p + '-paddingleft-2{padding-left:55px}');
customCss.push('li.list-' + p + '-paddingleft-3{padding-left:68px}');
break;
case 'num':
case 'num1':
customCss.push('li.list-' + p + '-paddingleft-1{padding-left:25px}');
break;
case 'num2':
customCss.push('li.list-' + p + '-paddingleft-1{padding-left:35px}');
customCss.push('li.list-' + p + '-paddingleft-2{padding-left:40px}');
break;
case 'dash':
customCss.push('li.list-' + p + '-paddingleft{padding-left:35px}');
break;
case 'dot':
customCss.push('li.list-' + p + '-paddingleft{padding-left:20px}');
}
}
customCss.push('.list-paddingleft-1{padding-left:0}');
customCss.push('.list-paddingleft-2{padding-left:' + me.options.listDefaultPaddingLeft + 'px}');
customCss.push('.list-paddingleft-3{padding-left:' + me.options.listDefaultPaddingLeft * 2 + 'px}');
//如果不给宽度会在自定应样式里出现滚动条
utils.cssRule('list', 'ol,ul{margin:0;pading:0;' + (browser.ie ? '' : 'width:95%') + '}li{clear:both;}' + customCss.join('\n'), me.document);
});
//单独处理剪切的问题
me.ready(function () {
domUtils.on(me.body, 'cut', function () {
setTimeout(function () {
var rng = me.selection.getRange(), li;
//trace:3416
if (!rng.collapsed) {
if (li = domUtils.findParentByTagName(rng.startContainer, 'li', true)) {
if (!li.nextSibling && domUtils.isEmptyBlock(li)) {
var pn = li.parentNode, node;
if (node = pn.previousSibling) {
domUtils.remove(pn);
rng.setStartAtLast(node).collapse(true);
rng.select(true);
} else if (node = pn.nextSibling) {
domUtils.remove(pn);
rng.setStartAtFirst(node).collapse(true);
rng.select(true);
} else {
var tmpNode = me.document.createElement('p');
domUtils.fillNode(me.document, tmpNode);
pn.parentNode.insertBefore(tmpNode, pn);
domUtils.remove(pn);
rng.setStart(tmpNode, 0).collapse(true);
rng.select(true);
}
}
}
}
})
})
});
function getStyle(node) {
var cls = node.className;
if (domUtils.hasClass(node, /custom_/)) {
return cls.match(/custom_(\w+)/)[1]
}
return domUtils.getStyle(node, 'list-style-type')
}
me.addListener('beforepaste', function (type, html) {
var me = this,
rng = me.selection.getRange(), li;
var root = UE.htmlparser(html.html, true);
if (li = domUtils.findParentByTagName(rng.startContainer, 'li', true)) {
var list = li.parentNode, tagName = list.tagName == 'OL' ? 'ul' : 'ol';
utils.each(root.getNodesByTagName(tagName), function (n) {
n.tagName = list.tagName;
n.setAttr();
if (n.parentNode === root) {
type = getStyle(list) || (list.tagName == 'OL' ? 'decimal' : 'disc')
} else {
var className = n.parentNode.getAttr('class');
if (className && /custom_/.test(className)) {
type = className.match(/custom_(\w+)/)[1]
} else {
type = n.parentNode.getStyle('list-style-type');
}
if (!type) {
type = list.tagName == 'OL' ? 'decimal' : 'disc';
}
}
var index = utils.indexOf(listStyle[list.tagName], type);
if (n.parentNode !== root)
index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
var currentStyle = listStyle[list.tagName][index];
if (customStyle[currentStyle]) {
n.setAttr('class', 'custom_' + currentStyle)
} else {
n.setStyle('list-style-type', currentStyle)
}
})
}
html.html = root.toHtml();
});
//导出时,去掉p标签
me.getOpt('disablePInList') === true && me.addOutputRule(function (root) {
utils.each(root.getNodesByTagName('li'), function (li) {
var newChildrens = [], index = 0;
utils.each(li.children, function (n) {
if (n.tagName == 'p') {
var tmpNode;
while (tmpNode = n.children.pop()) {
newChildrens.splice(index, 0, tmpNode);
tmpNode.parentNode = li;
lastNode = tmpNode;
}
tmpNode = newChildrens[newChildrens.length - 1];
if (!tmpNode || tmpNode.type != 'element' || tmpNode.tagName != 'br') {
var br = UE.uNode.createElement('br');
br.parentNode = li;
newChildrens.push(br);
}
index = newChildrens.length;
}
});
if (newChildrens.length) {
li.children = newChildrens;
}
});
});
//进入编辑器的li要套p标签
me.addInputRule(function (root) {
utils.each(root.getNodesByTagName('li'), function (li) {
var tmpP = UE.uNode.createElement('p');
for (var i = 0, ci; ci = li.children[i];) {
if (ci.type == 'text' || dtd.p[ci.tagName]) {
tmpP.appendChild(ci);
} else {
if (tmpP.firstChild()) {
li.insertBefore(tmpP, ci);
tmpP = UE.uNode.createElement('p');
i = i + 2;
} else {
i++;
}
}
}
if (tmpP.firstChild() && !tmpP.parentNode || !li.firstChild()) {
li.appendChild(tmpP);
}
//trace:3357
//p不能为空
if (!tmpP.firstChild()) {
tmpP.innerHTML(browser.ie ? ' ' : ' ')
}
//去掉末尾的空白
var p = li.firstChild();
var lastChild = p.lastChild();
if (lastChild && lastChild.type == 'text' && /^\s*$/.test(lastChild.data)) {
p.removeChild(lastChild)
}
});
if (me.options.autoTransWordToList) {
var orderlisttype = {
'num1': /^\d+\)/,
'decimal': /^\d+\./,
'lower-alpha': /^[a-z]+\)/,
'upper-alpha': /^[A-Z]+\./,
'cn': /^[\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+[\u3001]/,
'cn2': /^\([\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+\)/
},
unorderlisttype = {
'square': 'n'
};
function checkListType(content, container) {
var span = container.firstChild();
if (span && span.type == 'element' && span.tagName == 'span' && /Wingdings|Symbol/.test(span.getStyle('font-family'))) {
for (var p in unorderlisttype) {
if (unorderlisttype[p] == span.data) {
return p
}
}
return 'disc'
}
for (var p in orderlisttype) {
if (orderlisttype[p].test(content)) {
return p;
}
}
}
utils.each(root.getNodesByTagName('p'), function (node) {
if (node.getAttr('class') != 'MsoListParagraph') {
return
}
//word粘贴过来的会带有margin要去掉,但这样也可能会误命中一些央视
node.setStyle('margin', '');
node.setStyle('margin-left', '');
node.setAttr('class', '');
function appendLi(list, p, type) {
if (list.tagName == 'ol') {
if (browser.ie) {
var first = p.firstChild();
if (first.type == 'element' && first.tagName == 'span' && orderlisttype[type].test(first.innerText())) {
p.removeChild(first);
}
} else {
p.innerHTML(p.innerHTML().replace(orderlisttype[type], ''));
}
} else {
p.removeChild(p.firstChild())
}
var li = UE.uNode.createElement('li');
li.appendChild(p);
list.appendChild(li);
}
var tmp = node, type, cacheNode = node;
if (node.parentNode.tagName != 'li' && (type = checkListType(node.innerText(), node))) {
var list = UE.uNode.createElement(me.options.insertorderedlist.hasOwnProperty(type) ? 'ol' : 'ul');
if (customStyle[type]) {
list.setAttr('class', 'custom_' + type)
} else {
list.setStyle('list-style-type', type)
}
while (node && node.parentNode.tagName != 'li' && checkListType(node.innerText(), node)) {
tmp = node.nextSibling();
if (!tmp) {
node.parentNode.insertBefore(list, node)
}
appendLi(list, node, type);
node = tmp;
}
if (!list.parentNode && node && node.parentNode) {
node.parentNode.insertBefore(list, node)
}
}
var span = cacheNode.firstChild();
if (span && span.type == 'element' && span.tagName == 'span' && /^\s*( )+\s*$/.test(span.innerText())) {
span.parentNode.removeChild(span)
}
})
}
});
//调整索引标签
me.addListener('contentchange', function () {
adjustListStyle(me.document)
});
function adjustListStyle(doc, ignore) {
utils.each(domUtils.getElementsByTagName(doc, 'ol ul'), function (node) {
if (!domUtils.inDoc(node, doc))
return;
var parent = node.parentNode;
if (parent.tagName == node.tagName) {
var nodeStyleType = getStyle(node) || (node.tagName == 'OL' ? 'decimal' : 'disc'),
parentStyleType = getStyle(parent) || (parent.tagName == 'OL' ? 'decimal' : 'disc');
if (nodeStyleType == parentStyleType) {
var styleIndex = utils.indexOf(listStyle[node.tagName], nodeStyleType);
styleIndex = styleIndex + 1 == listStyle[node.tagName].length ? 0 : styleIndex + 1;
setListStyle(node, listStyle[node.tagName][styleIndex])
}
}
var index = 0, type = 2;
if (domUtils.hasClass(node, /custom_/)) {
if (!(/[ou]l/i.test(parent.tagName) && domUtils.hasClass(parent, /custom_/))) {
type = 1;
}
} else {
if (/[ou]l/i.test(parent.tagName) && domUtils.hasClass(parent, /custom_/)) {
type = 3;
}
}
var style = domUtils.getStyle(node, 'list-style-type');
style && (node.style.cssText = 'list-style-type:' + style);
node.className = utils.trim(node.className.replace(/list-paddingleft-\w+/, '')) + ' list-paddingleft-' + type;
utils.each(domUtils.getElementsByTagName(node, 'li'), function (li) {
li.style.cssText && (li.style.cssText = '');
if (!li.firstChild) {
domUtils.remove(li);
return;
}
if (li.parentNode !== node) {
return;
}
index++;
if (domUtils.hasClass(node, /custom_/)) {
var paddingLeft = 1, currentStyle = getStyle(node);
if (node.tagName == 'OL') {
if (currentStyle) {
switch (currentStyle) {
case 'cn':
case 'cn1':
case 'cn2':
if (index > 10 && (index % 10 == 0 || index > 10 && index < 20)) {
paddingLeft = 2
} else if (index > 20) {
paddingLeft = 3
}
break;
case 'num2':
if (index > 9) {
paddingLeft = 2
}
}
}
li.className = 'list-' + customStyle[currentStyle] + index + ' ' + 'list-' + currentStyle + '-paddingleft-' + paddingLeft;
} else {
li.className = 'list-' + customStyle[currentStyle] + ' ' + 'list-' + currentStyle + '-paddingleft';
}
} else {
li.className = li.className.replace(/list-[\w\-]+/gi, '');
}
var className = li.getAttribute('class');
if (className !== null && !className.replace(/\s/g, '')) {
domUtils.removeAttributes(li, 'class')
}
});
!ignore && adjustList(node, node.tagName.toLowerCase(), getStyle(node) || domUtils.getStyle(node, 'list-style-type'), true);
})
}
function adjustList(list, tag, style, ignoreEmpty) {
var nextList = list.nextSibling;
if (nextList && nextList.nodeType == 1 && nextList.tagName.toLowerCase() == tag && (getStyle(nextList) || domUtils.getStyle(nextList, 'list-style-type') || (tag == 'ol' ? 'decimal' : 'disc')) == style) {
domUtils.moveChild(nextList, list);
if (nextList.childNodes.length == 0) {
domUtils.remove(nextList);
}
}
if (nextList && domUtils.isFillChar(nextList)) {
domUtils.remove(nextList);
}
var preList = list.previousSibling;
if (preList && preList.nodeType == 1 && preList.tagName.toLowerCase() == tag && (getStyle(preList) || domUtils.getStyle(preList, 'list-style-type') || (tag == 'ol' ? 'decimal' : 'disc')) == style) {
domUtils.moveChild(list, preList);
}
if (preList && domUtils.isFillChar(preList)) {
domUtils.remove(preList);
}
!ignoreEmpty && domUtils.isEmptyBlock(list) && domUtils.remove(list);
if (getStyle(list)) {
adjustListStyle(list.ownerDocument, true)
}
}
function setListStyle(list, style) {
if (customStyle[style]) {
list.className = 'custom_' + style;
}
try {
domUtils.setStyle(list, 'list-style-type', style);
} catch (e) { }
}
function clearEmptySibling(node) {
var tmpNode = node.previousSibling;
if (tmpNode && domUtils.isEmptyBlock(tmpNode)) {
domUtils.remove(tmpNode);
}
tmpNode = node.nextSibling;
if (tmpNode && domUtils.isEmptyBlock(tmpNode)) {
domUtils.remove(tmpNode);
}
}
me.addListener('keydown', function (type, evt) {
function preventAndSave() {
evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
me.fireEvent('contentchange');
me.undoManger && me.undoManger.save();
}
function findList(node, filterFn) {
while (node && !domUtils.isBody(node)) {
if (filterFn(node)) {
return null
}
if (node.nodeType == 1 && /[ou]l/i.test(node.tagName)) {
return node;
}
node = node.parentNode;
}
return null;
}
var keyCode = evt.keyCode || evt.which;
if (keyCode == 13 && !evt.shiftKey) {//回车
var rng = me.selection.getRange(),
parent = domUtils.findParent(rng.startContainer, function (node) { return domUtils.isBlockElm(node) }, true),
li = domUtils.findParentByTagName(rng.startContainer, 'li', true);
if (parent && parent.tagName != 'PRE' && !li) {
var html = parent.innerHTML.replace(new RegExp(domUtils.fillChar, 'g'), '');
if (/^\s*1\s*\.[^\d]/.test(html)) {
parent.innerHTML = html.replace(/^\s*1\s*\./, '');
rng.setStartAtLast(parent).collapse(true).select();
me.__hasEnterExecCommand = true;
me.execCommand('insertorderedlist');
me.__hasEnterExecCommand = false;
}
}
var range = me.selection.getRange(),
start = findList(range.startContainer, function (node) {
return node.tagName == 'TABLE';
}),
end = range.collapsed ? start : findList(range.endContainer, function (node) {
return node.tagName == 'TABLE';
});
if (start && end && start === end) {
if (!range.collapsed) {
start = domUtils.findParentByTagName(range.startContainer, 'li', true);
end = domUtils.findParentByTagName(range.endContainer, 'li', true);
if (start && end && start === end) {
range.deleteContents();
li = domUtils.findParentByTagName(range.startContainer, 'li', true);
if (li && domUtils.isEmptyBlock(li)) {
pre = li.previousSibling;
next = li.nextSibling;
p = me.document.createElement('p');
domUtils.fillNode(me.document, p);
parentList = li.parentNode;
if (pre && next) {
range.setStart(next, 0).collapse(true).select(true);
domUtils.remove(li);
} else {
if (!pre && !next || !pre) {
parentList.parentNode.insertBefore(p, parentList);
} else {
li.parentNode.parentNode.insertBefore(p, parentList.nextSibling);
}
domUtils.remove(li);
if (!parentList.firstChild) {
domUtils.remove(parentList);
}
range.setStart(p, 0).setCursor();
}
preventAndSave();
return;
}
} else {
var tmpRange = range.cloneRange(),
bk = tmpRange.collapse(false).createBookmark();
range.deleteContents();
tmpRange.moveToBookmark(bk);
var li = domUtils.findParentByTagName(tmpRange.startContainer, 'li', true);
clearEmptySibling(li);
tmpRange.select();
preventAndSave();
return;
}
}
li = domUtils.findParentByTagName(range.startContainer, 'li', true);
if (li) {
if (domUtils.isEmptyBlock(li)) {
bk = range.createBookmark();
var parentList = li.parentNode;
if (li !== parentList.lastChild) {
domUtils.breakParent(li, parentList);
clearEmptySibling(li);
} else {
parentList.parentNode.insertBefore(li, parentList.nextSibling);
if (domUtils.isEmptyNode(parentList)) {
domUtils.remove(parentList);
}
}
//嵌套不处理
if (!dtd.$list[li.parentNode.tagName]) {
if (!domUtils.isBlockElm(li.firstChild)) {
p = me.document.createElement('p');
li.parentNode.insertBefore(p, li);
while (li.firstChild) {
p.appendChild(li.firstChild);
}
domUtils.remove(li);
} else {
domUtils.remove(li, true);
}
}
range.moveToBookmark(bk).select();
} else {
var first = li.firstChild;
if (!first || !domUtils.isBlockElm(first)) {
var p = me.document.createElement('p');
!li.firstChild && domUtils.fillNode(me.document, p);
while (li.firstChild) {
p.appendChild(li.firstChild);
}
li.appendChild(p);
first = p;
}
var span = me.document.createElement('span');
range.insertNode(span);
domUtils.breakParent(span, li);
var nextLi = span.nextSibling;
first = nextLi.firstChild;
if (!first) {
p = me.document.createElement('p');
domUtils.fillNode(me.document, p);
nextLi.appendChild(p);
first = p;
}
if (domUtils.isEmptyNode(first)) {
first.innerHTML = '';
domUtils.fillNode(me.document, first);
}
range.setStart(first, 0).collapse(true).shrinkBoundary().select();
domUtils.remove(span);
var pre = nextLi.previousSibling;
if (pre && domUtils.isEmptyBlock(pre)) {
pre.innerHTML = '
';
domUtils.fillNode(me.document, pre.firstChild);
}
}
// }
preventAndSave();
}
}
}
if (keyCode == 8) {
//修中ie中li下的问题
range = me.selection.getRange();
if (range.collapsed && domUtils.isStartInblock(range)) {
tmpRange = range.cloneRange().trimBoundary();
li = domUtils.findParentByTagName(range.startContainer, 'li', true);
//要在li的最左边,才能处理
if (li && domUtils.isStartInblock(tmpRange)) {
start = domUtils.findParentByTagName(range.startContainer, 'p', true);
if (start && start !== li.firstChild) {
var parentList = domUtils.findParentByTagName(start, ['ol', 'ul']);
domUtils.breakParent(start, parentList);
clearEmptySibling(start);
me.fireEvent('contentchange');
range.setStart(start, 0).setCursor(false, true);
me.fireEvent('saveScene');
domUtils.preventDefault(evt);
return;
}
if (li && (pre = li.previousSibling)) {
if (keyCode == 46 && li.childNodes.length) {
return;
}
//有可能上边的兄弟节点是个2级菜单,要追加到2级菜单的最后的li
if (dtd.$list[pre.tagName]) {
pre = pre.lastChild;
}
me.undoManger && me.undoManger.save();
first = li.firstChild;
if (domUtils.isBlockElm(first)) {
if (domUtils.isEmptyNode(first)) {
// range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true);
pre.appendChild(first);
range.setStart(first, 0).setCursor(false, true);
//first不是唯一的节点
while (li.firstChild) {
pre.appendChild(li.firstChild);
}
} else {
span = me.document.createElement('span');
range.insertNode(span);
//判断pre是否是空的节点,如果是
类型的空节点,干掉p标签防止它占位
if (domUtils.isEmptyBlock(pre)) {
pre.innerHTML = '';
}
domUtils.moveChild(li, pre);
range.setStartBefore(span).collapse(true).select(true);
domUtils.remove(span);
}
} else {
if (domUtils.isEmptyNode(li)) {
var p = me.document.createElement('p');
pre.appendChild(p);
range.setStart(p, 0).setCursor();
// range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true);
} else {
range.setEnd(pre, pre.childNodes.length).collapse().select(true);
while (li.firstChild) {
pre.appendChild(li.firstChild);
}
}
}
domUtils.remove(li);
me.fireEvent('contentchange');
me.fireEvent('saveScene');
domUtils.preventDefault(evt);
return;
}
//trace:980
if (li && !li.previousSibling) {
var parentList = li.parentNode;
var bk = range.createBookmark();
if (domUtils.isTagNode(parentList.parentNode, 'ol ul')) {
parentList.parentNode.insertBefore(li, parentList);
if (domUtils.isEmptyNode(parentList)) {
domUtils.remove(parentList)
}
} else {
while (li.firstChild) {
parentList.parentNode.insertBefore(li.firstChild, parentList);
}
domUtils.remove(li);
if (domUtils.isEmptyNode(parentList)) {
domUtils.remove(parentList)
}
}
range.moveToBookmark(bk).setCursor(false, true);
me.fireEvent('contentchange');
me.fireEvent('saveScene');
domUtils.preventDefault(evt);
return;
}
}
}
}
});
me.addListener('keyup', function (type, evt) {
var keyCode = evt.keyCode || evt.which;
if (keyCode == 8) {
var rng = me.selection.getRange(), list;
if (list = domUtils.findParentByTagName(rng.startContainer, ['ol', 'ul'], true)) {
adjustList(list, list.tagName.toLowerCase(), getStyle(list) || domUtils.getComputedStyle(list, 'list-style-type'), true)
}
}
});
//处理tab键
me.addListener('tabkeydown', function () {
var range = me.selection.getRange();
//控制级数
function checkLevel(li) {
if (me.options.maxListLevel != -1) {
var level = li.parentNode, levelNum = 0;
while (/[ou]l/i.test(level.tagName)) {
levelNum++;
level = level.parentNode;
}
if (levelNum >= me.options.maxListLevel) {
return true;
}
}
}
//只以开始为准
//todo 后续改进
var li = domUtils.findParentByTagName(range.startContainer, 'li', true);
if (li) {
var bk;
if (range.collapsed) {
if (checkLevel(li))
return true;
var parentLi = li.parentNode,
list = me.document.createElement(parentLi.tagName),
index = utils.indexOf(listStyle[list.tagName], getStyle(parentLi) || domUtils.getComputedStyle(parentLi, 'list-style-type'));
index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
var currentStyle = listStyle[list.tagName][index];
setListStyle(list, currentStyle);
if (domUtils.isStartInblock(range)) {
me.fireEvent('saveScene');
bk = range.createBookmark();
parentLi.insertBefore(list, li);
list.appendChild(li);
adjustList(list, list.tagName.toLowerCase(), currentStyle);
me.fireEvent('contentchange');
range.moveToBookmark(bk).select(true);
return true;
}
} else {
me.fireEvent('saveScene');
bk = range.createBookmark();
for (var i = 0, closeList, parents = domUtils.findParents(li), ci; ci = parents[i++];) {
if (domUtils.isTagNode(ci, 'ol ul')) {
closeList = ci;
break;
}
}
var current = li;
if (bk.end) {
while (current && !(domUtils.getPosition(current, bk.end) & domUtils.POSITION_FOLLOWING)) {
if (checkLevel(current)) {
current = domUtils.getNextDomNode(current, false, null, function (node) { return node !== closeList });
continue;
}
var parentLi = current.parentNode,
list = me.document.createElement(parentLi.tagName),
index = utils.indexOf(listStyle[list.tagName], getStyle(parentLi) || domUtils.getComputedStyle(parentLi, 'list-style-type'));
var currentIndex = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
var currentStyle = listStyle[list.tagName][currentIndex];
setListStyle(list, currentStyle);
parentLi.insertBefore(list, current);
while (current && !(domUtils.getPosition(current, bk.end) & domUtils.POSITION_FOLLOWING)) {
li = current.nextSibling;
list.appendChild(current);
if (!li || domUtils.isTagNode(li, 'ol ul')) {
if (li) {
while (li = li.firstChild) {
if (li.tagName == 'LI') {
break;
}
}
} else {
li = domUtils.getNextDomNode(current, false, null, function (node) { return node !== closeList });
}
break;
}
current = li;
}
adjustList(list, list.tagName.toLowerCase(), currentStyle);
current = li;
}
}
me.fireEvent('contentchange');
range.moveToBookmark(bk).select();
return true;
}
}
});
function getLi(start) {
while (start && !domUtils.isBody(start)) {
if (start.nodeName == 'TABLE') {
return null;
}
if (start.nodeName == 'LI') {
return start
}
start = start.parentNode;
}
}
/**
* 有序列表,与“insertunorderedlist”命令互斥
* @command insertorderedlist
* @method execCommand
* @param { String } command 命令字符串
* @param { String } style 插入的有序列表类型,值为:decimal,lower-alpha,lower-roman,upper-alpha,upper-roman,cn,cn1,cn2,num,num1,num2
* @example
* ```javascript
* editor.execCommand( 'insertorderedlist','decimal');
* ```
*/
/**
* 查询当前选区内容是否有序列表
* @command insertorderedlist
* @method queryCommandState
* @param { String } cmd 命令字符串
* @return { int } 如果当前选区是有序列表返回1,否则返回0
* @example
* ```javascript
* editor.queryCommandState( 'insertorderedlist' );
* ```
*/
/**
* 查询当前选区内容是否有序列表
* @command insertorderedlist
* @method queryCommandValue
* @param { String } cmd 命令字符串
* @return { String } 返回当前有序列表的类型,值为null或decimal,lower-alpha,lower-roman,upper-alpha,upper-roman,cn,cn1,cn2,num,num1,num2
* @example
* ```javascript
* editor.queryCommandValue( 'insertorderedlist' );
* ```
*/
/**
* 无序列表,与“insertorderedlist”命令互斥
* @command insertunorderedlist
* @method execCommand
* @param { String } command 命令字符串
* @param { String } style 插入的无序列表类型,值为:circle,disc,square,dash,dot
* @example
* ```javascript
* editor.execCommand( 'insertunorderedlist','circle');
* ```
*/
/**
* 查询当前是否有word文档粘贴进来的图片
* @command insertunorderedlist
* @method insertunorderedlist
* @param { String } command 命令字符串
* @return { int } 如果当前选区是无序列表返回1,否则返回0
* @example
* ```javascript
* editor.queryCommandState( 'insertunorderedlist' );
* ```
*/
/**
* 查询当前选区内容是否有序列表
* @command insertunorderedlist
* @method queryCommandValue
* @param { String } command 命令字符串
* @return { String } 返回当前无序列表的类型,值为null或circle,disc,square,dash,dot
* @example
* ```javascript
* editor.queryCommandValue( 'insertunorderedlist' );
* ```
*/
me.commands['insertorderedlist'] =
me.commands['insertunorderedlist'] = {
execCommand: function (command, style) {
if (!style) {
style = command.toLowerCase() == 'insertorderedlist' ? 'decimal' : 'disc';
}
var me = this,
range = this.selection.getRange(),
filterFn = function (node) {
return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' : !domUtils.isWhitespace(node);
},
tag = command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul',
frag = me.document.createDocumentFragment();
//去掉是因为会出现选到末尾,导致adjustmentBoundary缩到ol/ul的位置
//range.shrinkBoundary();//.adjustmentBoundary();
range.adjustmentBoundary().shrinkBoundary();
var bko = range.createBookmark(true),
start = getLi(me.document.getElementById(bko.start)),
modifyStart = 0,
end = getLi(me.document.getElementById(bko.end)),
modifyEnd = 0,
startParent, endParent,
list, tmp;
if (start || end) {
start && (startParent = start.parentNode);
if (!bko.end) {
end = start;
}
end && (endParent = end.parentNode);
if (startParent === endParent) {
while (start !== end) {
tmp = start;
start = start.nextSibling;
if (!domUtils.isBlockElm(tmp.firstChild)) {
var p = me.document.createElement('p');
while (tmp.firstChild) {
p.appendChild(tmp.firstChild);
}
tmp.appendChild(p);
}
frag.appendChild(tmp);
}
tmp = me.document.createElement('span');
startParent.insertBefore(tmp, end);
if (!domUtils.isBlockElm(end.firstChild)) {
p = me.document.createElement('p');
while (end.firstChild) {
p.appendChild(end.firstChild);
}
end.appendChild(p);
}
frag.appendChild(end);
domUtils.breakParent(tmp, startParent);
if (domUtils.isEmptyNode(tmp.previousSibling)) {
domUtils.remove(tmp.previousSibling);
}
if (domUtils.isEmptyNode(tmp.nextSibling)) {
domUtils.remove(tmp.nextSibling)
}
var nodeStyle = getStyle(startParent) || domUtils.getComputedStyle(startParent, 'list-style-type') || (command.toLowerCase() == 'insertorderedlist' ? 'decimal' : 'disc');
if (startParent.tagName.toLowerCase() == tag && nodeStyle == style) {
for (var i = 0, ci, tmpFrag = me.document.createDocumentFragment(); ci = frag.firstChild;) {
if (domUtils.isTagNode(ci, 'ol ul')) {
// 删除时,子列表不处理
// utils.each(domUtils.getElementsByTagName(ci,'li'),function(li){
// while(li.firstChild){
// tmpFrag.appendChild(li.firstChild);
// }
//
// });
tmpFrag.appendChild(ci);
} else {
while (ci.firstChild) {
tmpFrag.appendChild(ci.firstChild);
domUtils.remove(ci);
}
}
}
tmp.parentNode.insertBefore(tmpFrag, tmp);
} else {
list = me.document.createElement(tag);
setListStyle(list, style);
list.appendChild(frag);
tmp.parentNode.insertBefore(list, tmp);
}
domUtils.remove(tmp);
list && adjustList(list, tag, style);
range.moveToBookmark(bko).select();
return;
}
//开始
if (start) {
while (start) {
tmp = start.nextSibling;
if (domUtils.isTagNode(start, 'ol ul')) {
frag.appendChild(start);
} else {
var tmpfrag = me.document.createDocumentFragment(),
hasBlock = 0;
while (start.firstChild) {
if (domUtils.isBlockElm(start.firstChild)) {
hasBlock = 1;
}
tmpfrag.appendChild(start.firstChild);
}
if (!hasBlock) {
var tmpP = me.document.createElement('p');
tmpP.appendChild(tmpfrag);
frag.appendChild(tmpP);
} else {
frag.appendChild(tmpfrag);
}
domUtils.remove(start);
}
start = tmp;
}
startParent.parentNode.insertBefore(frag, startParent.nextSibling);
if (domUtils.isEmptyNode(startParent)) {
range.setStartBefore(startParent);
domUtils.remove(startParent);
} else {
range.setStartAfter(startParent);
}
modifyStart = 1;
}
if (end && domUtils.inDoc(endParent, me.document)) {
//结束
start = endParent.firstChild;
while (start && start !== end) {
tmp = start.nextSibling;
if (domUtils.isTagNode(start, 'ol ul')) {
frag.appendChild(start);
} else {
tmpfrag = me.document.createDocumentFragment();
hasBlock = 0;
while (start.firstChild) {
if (domUtils.isBlockElm(start.firstChild)) {
hasBlock = 1;
}
tmpfrag.appendChild(start.firstChild);
}
if (!hasBlock) {
tmpP = me.document.createElement('p');
tmpP.appendChild(tmpfrag);
frag.appendChild(tmpP);
} else {
frag.appendChild(tmpfrag);
}
domUtils.remove(start);
}
start = tmp;
}
var tmpDiv = domUtils.createElement(me.document, 'div', {
'tmpDiv': 1
});
domUtils.moveChild(end, tmpDiv);
frag.appendChild(tmpDiv);
domUtils.remove(end);
endParent.parentNode.insertBefore(frag, endParent);
range.setEndBefore(endParent);
if (domUtils.isEmptyNode(endParent)) {
domUtils.remove(endParent);
}
modifyEnd = 1;
}
}
if (!modifyStart) {
range.setStartBefore(me.document.getElementById(bko.start));
}
if (bko.end && !modifyEnd) {
range.setEndAfter(me.document.getElementById(bko.end));
}
range.enlarge(true, function (node) {
return notExchange[node.tagName];
});
frag = me.document.createDocumentFragment();
var bk = range.createBookmark(),
current = domUtils.getNextDomNode(bk.start, false, filterFn),
tmpRange = range.cloneRange(),
tmpNode,
block = domUtils.isBlockElm;
while (current && current !== bk.end && (domUtils.getPosition(current, bk.end) & domUtils.POSITION_PRECEDING)) {
if (current.nodeType == 3 || dtd.li[current.tagName]) {
if (current.nodeType == 1 && dtd.$list[current.tagName]) {
while (current.firstChild) {
frag.appendChild(current.firstChild);
}
tmpNode = domUtils.getNextDomNode(current, false, filterFn);
domUtils.remove(current);
current = tmpNode;
continue;
}
tmpNode = current;
tmpRange.setStartBefore(current);
while (current && current !== bk.end && (!block(current) || domUtils.isBookmarkNode(current))) {
tmpNode = current;
current = domUtils.getNextDomNode(current, false, null, function (node) {
return !notExchange[node.tagName];
});
}
if (current && block(current)) {
tmp = domUtils.getNextDomNode(tmpNode, false, filterFn);
if (tmp && domUtils.isBookmarkNode(tmp)) {
current = domUtils.getNextDomNode(tmp, false, filterFn);
tmpNode = tmp;
}
}
tmpRange.setEndAfter(tmpNode);
current = domUtils.getNextDomNode(tmpNode, false, filterFn);
var li = range.document.createElement('li');
li.appendChild(tmpRange.extractContents());
if (domUtils.isEmptyNode(li)) {
var tmpNode = range.document.createElement('p');
while (li.firstChild) {
tmpNode.appendChild(li.firstChild)
}
li.appendChild(tmpNode);
}
frag.appendChild(li);
} else {
current = domUtils.getNextDomNode(current, true, filterFn);
}
}
range.moveToBookmark(bk).collapse(true);
list = me.document.createElement(tag);
setListStyle(list, style);
list.appendChild(frag);
range.insertNode(list);
//当前list上下看能否合并
adjustList(list, tag, style);
//去掉冗余的tmpDiv
for (var i = 0, ci, tmpDivs = domUtils.getElementsByTagName(list, 'div'); ci = tmpDivs[i++];) {
if (ci.getAttribute('tmpDiv')) {
domUtils.remove(ci, true)
}
}
range.moveToBookmark(bko).select();
},
queryCommandState: function (command) {
var tag = command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul';
var path = this.selection.getStartElementPath();
for (var i = 0, ci; ci = path[i++];) {
if (ci.nodeName == 'TABLE') {
return 0
}
if (tag == ci.nodeName.toLowerCase()) {
return 1
};
}
return 0;
},
queryCommandValue: function (command) {
var tag = command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul';
var path = this.selection.getStartElementPath(),
node;
for (var i = 0, ci; ci = path[i++];) {
if (ci.nodeName == 'TABLE') {
node = null;
break;
}
if (tag == ci.nodeName.toLowerCase()) {
node = ci;
break;
};
}
return node ? getStyle(node) || domUtils.getComputedStyle(node, 'list-style-type') : null;
}
};
};
// plugins/source.js
/**
* 源码编辑插件
* @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() || '' + (browser.ie ? '' : ' ') + '
';
};
} else {
me.iframe.style.cssText = bakCssText;
var cont = sourceEditor.getContent() || '' + (browser.ie ? '' : ' ') + '
';
//处理掉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 = '' + (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(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"
});
});
}
};
})();
// plugins/enterkey.js
///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', 'caption', 'table'], 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();
}
}
//没有站位符,会出现多行的问题
browser.opera && range.select();
} else {
me.fireEvent('saveScene', true, true)
}
}
});
me.addListener('keydown', function (type, evt) {
var keyCode = evt.keyCode || evt.which;
if (keyCode == 13) {//回车
if (me.fireEvent('beforeenterkeydown')) {
domUtils.preventDefault(evt);
return;
}
me.fireEvent('saveScene', true, true);
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;
}
}
if (tag == 'p') {
if (!browser.ie) {
start = domUtils.findParentByTagName(range.startContainer, ['ol', 'ul', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'caption'], true);
//opera下执行formatblock会在table的场景下有问题,回车在opera原生支持很好,所以暂时在opera去掉调用这个原生的command
//trace:2431
if (!start && !browser.opera) {
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();
}
}
}
});
};
// plugins/keystrokes.js
/* 处理特殊键的兼容性问题 */
UE.plugins['keystrokes'] = function () {
var me = this;
var collapsed = true;
me.addListener('keydown', function (type, evt) {
var keyCode = evt.keyCode || evt.which,
rng = me.selection.getRange();
//处理全选的情况
if (!rng.collapsed && !(evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) && (keyCode >= 65 && keyCode <= 90
|| keyCode >= 48 && keyCode <= 57 ||
keyCode >= 96 && keyCode <= 111 || {
13: 1,
8: 1,
46: 1
}[keyCode])
) {
var tmpNode = rng.startContainer;
if (domUtils.isFillChar(tmpNode)) {
rng.setStartBefore(tmpNode)
}
tmpNode = rng.endContainer;
if (domUtils.isFillChar(tmpNode)) {
rng.setEndAfter(tmpNode)
}
rng.txtToElmBoundary();
//结束边界可能放到了br的前边,要把br包含进来
// x[xxx]
if (rng.endContainer && rng.endContainer.nodeType == 1) {
tmpNode = rng.endContainer.childNodes[rng.endOffset];
if (tmpNode && domUtils.isBr(tmpNode)) {
rng.setEndAfter(tmpNode);
}
}
if (rng.startOffset == 0) {
tmpNode = rng.startContainer;
if (domUtils.isBoundaryNode(tmpNode, 'firstChild')) {
tmpNode = rng.endContainer;
if (rng.endOffset == (tmpNode.nodeType == 3 ? tmpNode.nodeValue.length : tmpNode.childNodes.length) && domUtils.isBoundaryNode(tmpNode, 'lastChild')) {
me.fireEvent('saveScene');
me.body.innerHTML = '
' + (browser.ie ? '' : ' ') + '
';
rng.setStart(me.body.firstChild, 0).setCursor(false, true);
me._selectionChange();
return;
}
}
}
}
//处理backspace
if (keyCode == keymap.Backspace) {
rng = me.selection.getRange();
collapsed = rng.collapsed;
if (me.fireEvent('delkeydown', evt)) {
return;
}
var start, end;
//避免按两次删除才能生效的问题
if (rng.collapsed && rng.inFillChar()) {
start = rng.startContainer;
if (domUtils.isFillChar(start)) {
rng.setStartBefore(start).shrinkBoundary(true).collapse(true);
domUtils.remove(start)
} else {
start.nodeValue = start.nodeValue.replace(new RegExp('^' + domUtils.fillChar), '');
rng.startOffset--;
rng.collapse(true).select(true)
}
}
//解决选中control元素不能删除的问题
if (start = rng.getClosedNode()) {
me.fireEvent('saveScene');
rng.setStartBefore(start);
domUtils.remove(start);
rng.setCursor();
me.fireEvent('saveScene');
domUtils.preventDefault(evt);
return;
}
//阻止在table上的删除
if (!browser.ie) {
start = domUtils.findParentByTagName(rng.startContainer, 'table', true);
end = domUtils.findParentByTagName(rng.endContainer, 'table', true);
if (start && !end || !start && end || start !== end) {
evt.preventDefault();
return;
}
}
}
//处理tab键的逻辑
if (keyCode == keymap.Tab) {
//不处理以下标签
var excludeTagNameForTabKey = {
'ol': 1,
'ul': 1,
'table': 1
};
//处理组件里的tab按下事件
if (me.fireEvent('tabkeydown', evt)) {
domUtils.preventDefault(evt);
return;
}
var range = me.selection.getRange();
me.fireEvent('saveScene');
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 + domUtils.fillChar;
if (range.collapsed) {
range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
} else {
var filterFn = function (node) {
return domUtils.isBlockElm(node) && !excludeTagNameForTabKey[node.tagName.toLowerCase()]
};
//普通的情况
start = domUtils.findParent(range.startContainer, filterFn, true);
end = domUtils.findParent(range.endContainer, filterFn, true);
if (start && end && start === end) {
range.deleteContents();
range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
} else {
var bookmark = range.createBookmark();
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();
}
}
domUtils.preventDefault(evt)
}
//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,
rng, me = this;
if (keyCode == keymap.Backspace) {
if (me.fireEvent('delkeyup')) {
return;
}
rng = me.selection.getRange();
if (rng.collapsed) {
var tmpNode,
autoClearTagName = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
if (tmpNode = domUtils.findParentByTagName(rng.startContainer, autoClearTagName, true)) {
if (domUtils.isEmptyBlock(tmpNode)) {
var pre = tmpNode.previousSibling;
if (pre && pre.nodeName != 'TABLE') {
domUtils.remove(tmpNode);
rng.setStartAtLast(pre).setCursor(false, true);
return;
} else {
var next = tmpNode.nextSibling;
if (next && next.nodeName != 'TABLE') {
domUtils.remove(tmpNode);
rng.setStartAtFirst(next).setCursor(false, true);
return;
}
}
}
}
//处理当删除到body时,要重新给p标签展位
if (domUtils.isBody(rng.startContainer)) {
var tmpNode = domUtils.createElement(me.document, 'p', {
'innerHTML': browser.ie ? domUtils.fillChar : ' '
});
rng.insertNode(tmpNode).setStart(tmpNode, 0).setCursor(false, true);
}
}
//chrome下如果删除了inline标签,浏览器会有记忆,在输入文字还是会套上刚才删除的标签,所以这里再选一次就不会了
if (!collapsed && (rng.startContainer.nodeType == 3 || rng.startContainer.nodeType == 1 && domUtils.isEmptyBlock(rng.startContainer))) {
if (browser.ie) {
var span = rng.document.createElement('span');
rng.insertNode(span).setStartBefore(span).collapse(true);
rng.select();
domUtils.remove(span)
} else {
rng.select()
}
}
}
})
};
// plugins/fiximgclick.js
///import core
///commands 修复chrome下图片不能点击的问题,出现八个角可改变大小
///commandsName FixImgClick
///commandsTitle 修复chrome下图片不能点击的问题,出现八个角可改变大小
//修复chrome下图片不能点击的问题,出现八个角可改变大小
UE.plugins['fiximgclick'] = (function () {
var elementUpdated = false;
function Scale() {
this.editor = null;
this.resizer = null;
this.cover = null;
this.doc = document;
this.prePos = { x: 0, y: 0 };
this.startPos = { x: 0, y: 0 };
}
(function () {
var rect = [
//[left, top, width, height]
[0, 0, -1, -1],
[0, 0, 0, -1],
[0, 0, 1, -1],
[0, 0, -1, 0],
[0, 0, 1, 0],
[0, 0, -1, 1],
[0, 0, 0, 1],
[0, 0, 1, 1]
];
Scale.prototype = {
init: function (editor) {
var me = this;
me.editor = editor;
me.startPos = this.prePos = { x: 0, y: 0 };
me.dragId = -1;
var hands = [],
cover = me.cover = document.createElement('div'),
resizer = me.resizer = document.createElement('div');
cover.id = me.editor.ui.id + '_imagescale_cover';
cover.style.cssText = 'position:absolute;display:none;z-index:' + (me.editor.options.zIndex) + ';filter:alpha(opacity=0); opacity:0;background:#CCC;';
domUtils.on(cover, 'mousedown click', function () {
me.hide();
});
for (i = 0; i < 8; i++) {
hands.push(' ');
}
resizer.id = me.editor.ui.id + '_imagescale';
resizer.className = 'edui-editor-imagescale';
resizer.innerHTML = hands.join('');
resizer.style.cssText += ';display:none;border:1px solid #3b77ff;z-index:' + (me.editor.options.zIndex) + ';';
me.editor.ui.getDom().appendChild(cover);
me.editor.ui.getDom().appendChild(resizer);
me.initStyle();
me.initEvents();
},
initStyle: function () {
utils.cssRule('imagescale', '.edui-editor-imagescale{display:none;position:absolute;border:1px solid #38B2CE;cursor:hand;-webkit-box-sizing: content-box;-moz-box-sizing: content-box;box-sizing: content-box;}' +
'.edui-editor-imagescale span{position:absolute;width:6px;height:6px;overflow:hidden;font-size:0px;display:block;background-color:#3C9DD0;}'
+ '.edui-editor-imagescale .edui-editor-imagescale-hand0{cursor:nw-resize;top:0;margin-top:-4px;left:0;margin-left:-4px;}'
+ '.edui-editor-imagescale .edui-editor-imagescale-hand1{cursor:n-resize;top:0;margin-top:-4px;left:50%;margin-left:-4px;}'
+ '.edui-editor-imagescale .edui-editor-imagescale-hand2{cursor:ne-resize;top:0;margin-top:-4px;left:100%;margin-left:-3px;}'
+ '.edui-editor-imagescale .edui-editor-imagescale-hand3{cursor:w-resize;top:50%;margin-top:-4px;left:0;margin-left:-4px;}'
+ '.edui-editor-imagescale .edui-editor-imagescale-hand4{cursor:e-resize;top:50%;margin-top:-4px;left:100%;margin-left:-3px;}'
+ '.edui-editor-imagescale .edui-editor-imagescale-hand5{cursor:sw-resize;top:100%;margin-top:-3px;left:0;margin-left:-4px;}'
+ '.edui-editor-imagescale .edui-editor-imagescale-hand6{cursor:s-resize;top:100%;margin-top:-3px;left:50%;margin-left:-4px;}'
+ '.edui-editor-imagescale .edui-editor-imagescale-hand7{cursor:se-resize;top:100%;margin-top:-3px;left:100%;margin-left:-3px;}');
},
initEvents: function () {
var me = this;
me.startPos.x = me.startPos.y = 0;
me.isDraging = false;
},
_eventHandler: function (e) {
var me = this;
switch (e.type) {
case 'mousedown':
var hand = e.target || e.srcElement, hand;
if (hand.className.indexOf('edui-editor-imagescale-hand') != -1 && me.dragId == -1) {
me.dragId = hand.className.slice(-1);
me.startPos.x = me.prePos.x = e.clientX;
me.startPos.y = me.prePos.y = e.clientY;
domUtils.on(me.doc, 'mousemove', me.proxy(me._eventHandler, me));
}
break;
case 'mousemove':
if (me.dragId != -1) {
me.updateContainerStyle(me.dragId, { x: e.clientX - me.prePos.x, y: e.clientY - me.prePos.y });
me.prePos.x = e.clientX;
me.prePos.y = e.clientY;
elementUpdated = true;
me.updateTargetElement();
}
break;
case 'mouseup':
if (me.dragId != -1) {
me.updateContainerStyle(me.dragId, { x: e.clientX - me.prePos.x, y: e.clientY - me.prePos.y });
me.updateTargetElement();
if (me.target.parentNode) me.attachTo(me.target);
me.dragId = -1;
}
domUtils.un(me.doc, 'mousemove', me.proxy(me._eventHandler, me));
//修复只是点击挪动点,但没有改变大小,不应该触发contentchange
if (elementUpdated) {
elementUpdated = false;
me.editor.fireEvent('contentchange');
}
break;
default:
break;
}
},
updateTargetElement: function () {
var me = this;
domUtils.setStyles(me.target, {
'width': me.resizer.style.width,
'height': me.resizer.style.height
});
me.target.width = parseInt(me.resizer.style.width);
me.target.height = parseInt(me.resizer.style.height);
me.attachTo(me.target);
},
updateContainerStyle: function (dir, offset) {
var me = this,
dom = me.resizer, tmp;
if (rect[dir][0] != 0) {
tmp = parseInt(dom.style.left) + offset.x;
dom.style.left = me._validScaledProp('left', tmp) + 'px';
}
if (rect[dir][1] != 0) {
tmp = parseInt(dom.style.top) + offset.y;
dom.style.top = me._validScaledProp('top', tmp) + 'px';
}
if (rect[dir][2] != 0) {
tmp = dom.clientWidth + rect[dir][2] * offset.x;
dom.style.width = me._validScaledProp('width', tmp) + 'px';
}
if (rect[dir][3] != 0) {
tmp = dom.clientHeight + rect[dir][3] * offset.y;
dom.style.height = me._validScaledProp('height', tmp) + 'px';
}
},
_validScaledProp: function (prop, value) {
var ele = this.resizer,
wrap = document;
value = isNaN(value) ? 0 : value;
switch (prop) {
case 'left':
return value < 0 ? 0 : (value + ele.clientWidth) > wrap.clientWidth ? wrap.clientWidth - ele.clientWidth : value;
case 'top':
return value < 0 ? 0 : (value + ele.clientHeight) > wrap.clientHeight ? wrap.clientHeight - ele.clientHeight : value;
case 'width':
return value <= 0 ? 1 : (value + ele.offsetLeft) > wrap.clientWidth ? wrap.clientWidth - ele.offsetLeft : value;
case 'height':
return value <= 0 ? 1 : (value + ele.offsetTop) > wrap.clientHeight ? wrap.clientHeight - ele.offsetTop : value;
}
},
hideCover: function () {
this.cover.style.display = 'none';
},
showCover: function () {
var me = this,
editorPos = domUtils.getXY(me.editor.ui.getDom()),
iframePos = domUtils.getXY(me.editor.iframe);
domUtils.setStyles(me.cover, {
'width': me.editor.iframe.offsetWidth + 'px',
'height': me.editor.iframe.offsetHeight + 'px',
'top': iframePos.y - editorPos.y + 'px',
'left': iframePos.x - editorPos.x + 'px',
'position': 'absolute',
'display': ''
})
},
show: function (targetObj) {
var me = this;
me.resizer.style.display = 'block';
if (targetObj) me.attachTo(targetObj);
domUtils.on(this.resizer, 'mousedown', me.proxy(me._eventHandler, me));
domUtils.on(me.doc, 'mouseup', me.proxy(me._eventHandler, me));
me.showCover();
me.editor.fireEvent('afterscaleshow', me);
me.editor.fireEvent('saveScene');
},
hide: function () {
var me = this;
me.hideCover();
me.resizer.style.display = 'none';
domUtils.un(me.resizer, 'mousedown', me.proxy(me._eventHandler, me));
domUtils.un(me.doc, 'mouseup', me.proxy(me._eventHandler, me));
me.editor.fireEvent('afterscalehide', me);
},
proxy: function (fn, context) {
return function (e) {
return fn.apply(context || this, arguments);
};
},
attachTo: function (targetObj) {
var me = this,
target = me.target = targetObj,
resizer = this.resizer,
imgPos = domUtils.getXY(target),
iframePos = domUtils.getXY(me.editor.iframe),
editorPos = domUtils.getXY(resizer.parentNode);
domUtils.setStyles(resizer, {
'width': target.width + 'px',
'height': target.height + 'px',
'left': iframePos.x + imgPos.x - me.editor.document.body.scrollLeft - editorPos.x - parseInt(resizer.style.borderLeftWidth) + 'px',
'top': iframePos.y + imgPos.y - me.editor.document.body.scrollTop - editorPos.y - parseInt(resizer.style.borderTopWidth) + 'px'
});
}
}
})();
return function () {
var me = this,
imageScale;
me.setOpt('imageScaleEnabled', true);
if (!browser.ie && me.options.imageScaleEnabled) {
me.addListener('click', function (type, e) {
var range = me.selection.getRange(),
img = range.getClosedNode();
if (img && img.tagName == 'IMG' && me.body.contentEditable != "false") {
if (img.className.indexOf("edui-faked-music") != -1 ||
img.getAttribute("anchorname") ||
domUtils.hasClass(img, 'loadingclass') ||
domUtils.hasClass(img, 'loaderrorclass')) { return }
if (!imageScale) {
imageScale = new Scale();
imageScale.init(me);
me.ui.getDom().appendChild(imageScale.resizer);
var _keyDownHandler = function (e) {
imageScale.hide();
if (imageScale.target) me.selection.getRange().selectNode(imageScale.target).select();
}, _mouseDownHandler = function (e) {
var ele = e.target || e.srcElement;
if (ele && (ele.className === undefined || ele.className.indexOf('edui-editor-imagescale') == -1)) {
_keyDownHandler(e);
}
}, timer;
me.addListener('afterscaleshow', function (e) {
me.addListener('beforekeydown', _keyDownHandler);
me.addListener('beforemousedown', _mouseDownHandler);
domUtils.on(document, 'keydown', _keyDownHandler);
domUtils.on(document, 'mousedown', _mouseDownHandler);
me.selection.getNative().removeAllRanges();
});
me.addListener('afterscalehide', function (e) {
me.removeListener('beforekeydown', _keyDownHandler);
me.removeListener('beforemousedown', _mouseDownHandler);
domUtils.un(document, 'keydown', _keyDownHandler);
domUtils.un(document, 'mousedown', _mouseDownHandler);
var target = imageScale.target;
if (target.parentNode) {
me.selection.getRange().selectNode(target).select();
}
});
//TODO 有iframe的情况,mousedown不能往下传。。
domUtils.on(imageScale.resizer, 'mousedown', function (e) {
me.selection.getNative().removeAllRanges();
var ele = e.target || e.srcElement;
if (ele && ele.className.indexOf('edui-editor-imagescale-hand') == -1) {
timer = setTimeout(function () {
imageScale.hide();
if (imageScale.target) me.selection.getRange().selectNode(ele).select();
}, 200);
}
});
domUtils.on(imageScale.resizer, 'mouseup', function (e) {
var ele = e.target || e.srcElement;
if (ele && ele.className.indexOf('edui-editor-imagescale-hand') == -1) {
clearTimeout(timer);
}
});
}
imageScale.show(img);
} else {
if (imageScale && imageScale.resizer.style.display != 'none') imageScale.hide();
}
});
}
if (browser.webkit) {
me.addListener('click', function (type, e) {
if (e.target.tagName == 'IMG' && me.body.contentEditable != "false") {
var range = new dom.Range(me.document);
range.selectNode(e.target).select();
}
});
}
}
})();
// plugins/autolink.js
///import core
///commands 为非ie浏览器自动添加a标签
///commandsName AutoLink
///commandsTitle 自动增加链接
/**
* @description 为非ie浏览器自动添加a标签
* @author zhanyi
*/
UE.plugin.register('autolink', function () {
var cont = 0;
return !browser.ie ? {
bindEvents: {
'reset': function () {
cont = 0;
},
'keydown': function (type, evt) {
var me = this;
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);
}
}
//range的开始边界已经在a标签里的不再处理
if (domUtils.findParentByTagName(range.startContainer, 'a', true)) {
return;
}
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('_src', utils.html(href));
a.href = utils.html(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();
}
}
}
}
} : {}
}, function () {
var keyCodes = {
37: 1, 38: 1, 39: 1, 40: 1,
13: 1, 32: 1
};
function checkIsCludeLink(node) {
if (node.nodeType == 3) {
return null
}
if (node.nodeName == 'A') {
return node;
}
var lastChild = node.lastChild;
while (lastChild) {
if (lastChild.nodeName == 'A') {
return lastChild;
}
if (lastChild.nodeType == 3) {
if (domUtils.isWhitespace(lastChild)) {
lastChild = lastChild.previousSibling;
continue;
}
return null
}
lastChild = lastChild.lastChild;
}
}
browser.ie && this.addListener('keyup', function (cmd, evt) {
var me = this, keyCode = evt.keyCode;
if (keyCodes[keyCode]) {
var rng = me.selection.getRange();
var start = rng.startContainer;
if (keyCode == 13) {
while (start && !domUtils.isBody(start) && !domUtils.isBlockElm(start)) {
start = start.parentNode;
}
if (start && !domUtils.isBody(start) && start.nodeName == 'P') {
var pre = start.previousSibling;
if (pre && pre.nodeType == 1) {
var pre = checkIsCludeLink(pre);
if (pre && !pre.getAttribute('_href')) {
domUtils.remove(pre, true);
}
}
}
} else if (keyCode == 32) {
if (start.nodeType == 3 && /^\s$/.test(start.nodeValue)) {
start = start.previousSibling;
if (start && start.nodeName == 'A' && !start.getAttribute('_href')) {
domUtils.remove(start, true);
}
}
} else {
start = domUtils.findParentByTagName(start, 'a', true);
if (start && !start.getAttribute('_href')) {
var bk = rng.createBookmark();
domUtils.remove(start, true);
rng.moveToBookmark(bk).select(true)
}
}
}
});
}
);
// plugins/autoheight.js
///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,
lastHeight = 0,
options = me.options,
currentHeight,
timer;
function adjustHeight() {
var me = this;
clearTimeout(timer);
if (isFullscreen) return;
if (!me.queryCommandState || me.queryCommandState && me.queryCommandState('source') != 1) {
timer = setTimeout(function () {
var node = me.body.lastChild;
while (node && node.nodeType != 1) {
node = node.previousSibling;
}
if (node && node.nodeType == 1) {
node.style.clear = 'both';
currentHeight = Math.max(domUtils.getXY(node).y + node.offsetHeight + 25, Math.max(options.minFrameHeight, options.initialFrameHeight));
if (currentHeight != lastHeight) {
if (currentHeight !== parseInt(me.iframe.parentNode.style.height)) {
me.iframe.parentNode.style.height = currentHeight + 'px';
}
me.body.style.height = currentHeight + 'px';
lastHeight = currentHeight;
}
domUtils.removeStyle(node, 'clear');
}
}, 50)
}
}
var isFullscreen;
me.addListener('fullscreenchanged', function (cmd, f) {
isFullscreen = f
});
me.addListener('destroy', function () {
me.removeListener('contentchange afterinserthtml keyup mouseup', adjustHeight)
});
me.enableAutoHeight = function () {
var me = this;
if (!me.autoHeightEnabled) {
return;
}
var doc = me.document;
me.autoHeightEnabled = true;
bakOverflow = doc.body.style.overflowY;
doc.body.style.overflowY = 'hidden';
me.addListener('contentchange afterinserthtml keyup mouseup', adjustHeight);
//ff不给事件算得不对
setTimeout(function () {
adjustHeight.call(me);
}, 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.on('setHeight', function () {
me.disableAutoHeight()
});
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 () {
//trace:3681
adjustHeight.call(me);
}, 100);
});
//修复内容过多时,回到顶部,顶部内容被工具栏遮挡问题
var lastScrollY;
window.onscroll = function () {
if (lastScrollY === null) {
lastScrollY = this.scrollY
} else if (this.scrollY == 0 && lastScrollY != 0) {
me.window.scrollTo(0, 0);
lastScrollY = null;
}
}
});
};
// plugins/autofloat.js
///import core
///commands 悬浮工具栏
///commandsName AutoFloat,autoFloatEnabled
///commandsTitle 悬浮工具栏
/**
* modified by chengchao01
* 注意: 引入此功能后,在IE6下会将body的背景图片覆盖掉!
*/
UE.plugins['autofloat'] = function () {
var me = this,
lang = me.getLang();
me.setOpt({
topOffset: 0
});
var optsAutoFloatEnabled = me.options.autoFloatEnabled !== false,
topOffset = me.options.topOffset;
//如果不固定toolbar的位置,则直接退出
if (!optsAutoFloatEnabled) {
return;
}
var uiUtils = UE.ui.uiUtils,
LteIE6 = browser.ie && browser.version <= 6,
quirks = browser.quirks;
function checkHasUI() {
if (!UE.ui) {
alert(lang.autofloatMsg);
return 0;
}
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 && browser.ie)) {
if (toolbarBox.style.position != 'absolute') {
toolbarBox.style.position = 'absolute';
}
toolbarBox.style.top = (document.body.scrollTop || document.documentElement.scrollTop) - orgTop + topOffset + '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 = topOffset + "px";
((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);
var offset = me.options.toolbarTopOffset || 0;
if (rect3.top < 0 && rect3.bottom - toolbarBox.offsetHeight > offset) {
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)) {
//加载了ui组件,但在new时,没有加载ui,导致编辑器实例上没有ui类,所以这里做判断
if (!me.ui) {
return;
}
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();
}
domUtils.on(window, ['scroll', 'resize'], updateFloating);
me.addListener('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();
}, 0);
});
me.addListener("clearDoc", function () {
setTimeout(function () {
updateFloating();
}, 0);
})
}
});
};
// plugins/video.js
/**
* video插件, 为UEditor提供视频插入支持
* @file
* @since 1.2.6.1
*/
UE.plugins['video'] = function () {
var me = this;
/**
* 创建插入视频字符窜
* @param url 视频地址
* @param width 视频宽度
* @param height 视频高度
* @param align 视频对齐
* @param toEmbed 是否以flash代替显示
* @param addParagraph 是否需要添加P 标签
*/
function creatInsertStr(url, width, height, id, align, classname, type) {
url = utils.unhtmlForUrl(url);
align = utils.unhtml(align);
classname = utils.unhtml(classname);
width = parseInt(width, 10) || 0;
height = parseInt(height, 10) || 0;
var str;
switch (type) {
case 'image':
str = ' '
break;
case 'embed':
str = '';
break;
case 'video':
var ext = url.substr(url.lastIndexOf('.') + 1);
if (ext == 'ogv') ext = 'ogg';
str = '' +
' ';
break;
}
return str;
}
function switchImgAndVideo(root, img2video) {
utils.each(root.getNodesByTagName(img2video ? 'img' : 'embed video'), function (node) {
var className = node.getAttr('class');
if (className && className.indexOf('edui-faked-video') != -1) {
var html = creatInsertStr(img2video ? node.getAttr('_url') : node.getAttr('src'), node.getAttr('width'), node.getAttr('height'), null, node.getStyle('float') || '', className, img2video ? 'embed' : 'image');
node.parentNode.replaceChild(UE.uNode.createElement(html), node);
}
if (className && className.indexOf('edui-upload-video') != -1) {
var html = creatInsertStr(img2video ? node.getAttr('_url') : node.getAttr('src'), node.getAttr('width'), node.getAttr('height'), null, node.getStyle('float') || '', className, img2video ? 'video' : 'image');
node.parentNode.replaceChild(UE.uNode.createElement(html), node);
}
})
}
me.addOutputRule(function (root) {
switchImgAndVideo(root, true)
});
me.addInputRule(function (root) {
switchImgAndVideo(root)
});
/**
* 插入视频
* @command insertvideo
* @method execCommand
* @param { String } cmd 命令字符串
* @param { Object } videoAttr 键值对对象, 描述一个视频的所有属性
* @example
* ```javascript
*
* var videoAttr = {
* //视频地址
* url: 'http://www.youku.com/xxx',
* //视频宽高值, 单位px
* width: 200,
* height: 100
* };
*
* //editor 是编辑器实例
* //向编辑器插入单个视频
* editor.execCommand( 'insertvideo', videoAttr );
* ```
*/
/**
* 插入视频
* @command insertvideo
* @method execCommand
* @param { String } cmd 命令字符串
* @param { Array } videoArr 需要插入的视频的数组, 其中的每一个元素都是一个键值对对象, 描述了一个视频的所有属性
* @example
* ```javascript
*
* var videoAttr1 = {
* //视频地址
* url: 'http://www.youku.com/xxx',
* //视频宽高值, 单位px
* width: 200,
* height: 100
* },
* videoAttr2 = {
* //视频地址
* url: 'http://www.youku.com/xxx',
* //视频宽高值, 单位px
* width: 200,
* height: 100
* }
*
* //editor 是编辑器实例
* //该方法将会向编辑器内插入两个视频
* editor.execCommand( 'insertvideo', [ videoAttr1, videoAttr2 ] );
* ```
*/
/**
* 查询当前光标所在处是否是一个视频
* @command insertvideo
* @method queryCommandState
* @param { String } cmd 需要查询的命令字符串
* @return { int } 如果当前光标所在处的元素是一个视频对象, 则返回1,否则返回0
* @example
* ```javascript
*
* //editor 是编辑器实例
* editor.queryCommandState( 'insertvideo' );
* ```
*/
me.commands["insertvideo"] = {
execCommand: function (cmd, videoObjs, type) {
videoObjs = utils.isArray(videoObjs) ? videoObjs : [videoObjs];
var html = [], id = 'tmpVedio', cl;
for (var i = 0, vi, len = videoObjs.length; i < len; i++) {
vi = videoObjs[i];
cl = (type == 'upload' ? 'edui-upload-video video-js vjs-default-skin' : 'edui-faked-video');
html.push(creatInsertStr(vi.url, vi.width || 420, vi.height || 280, id + i, null, cl, 'image'));
}
me.execCommand("inserthtml", html.join(""), true);
var rng = this.selection.getRange();
for (var i = 0, len = videoObjs.length; i < len; i++) {
var img = this.document.getElementById('tmpVedio' + i);
domUtils.removeAttributes(img, 'id');
rng.selectNode(img).select();
me.execCommand('imagefloat', videoObjs[i].align)
}
},
queryCommandState: function () {
var img = me.selection.getRange().getClosedNode(),
flag = img && (img.className == "edui-faked-video" || img.className.indexOf("edui-upload-video") != -1);
return flag ? 1 : 0;
}
};
};
// plugins/table.core.js
/**
* Created with JetBrains WebStorm.
* User: taoqili
* Date: 13-1-18
* Time: 上午11:09
* To change this template use File | Settings | File Templates.
*/
/**
* UE表格操作类
* @param table
* @constructor
*/
(function () {
var UETable = UE.UETable = function (table) {
this.table = table;
this.indexTable = [];
this.selectedTds = [];
this.cellsRange = {};
this.update(table);
};
//===以下为静态工具方法===
UETable.removeSelectedClass = function (cells) {
utils.each(cells, function (cell) {
domUtils.removeClasses(cell, "selectTdClass");
})
};
UETable.addSelectedClass = function (cells) {
utils.each(cells, function (cell) {
domUtils.addClass(cell, "selectTdClass");
})
};
UETable.isEmptyBlock = function (node) {
var reg = new RegExp(domUtils.fillChar, 'g');
if (node[browser.ie ? 'innerText' : 'textContent'].replace(/^\s*$/, '').replace(reg, '').length > 0) {
return 0;
}
for (var i in dtd.$isNotEmpty) if (dtd.$isNotEmpty.hasOwnProperty(i)) {
if (node.getElementsByTagName(i).length) {
return 0;
}
}
return 1;
};
UETable.getWidth = function (cell) {
if (!cell) return 0;
return parseInt(domUtils.getComputedStyle(cell, "width"), 10);
};
/**
* 获取单元格或者单元格组的“对齐”状态。 如果当前的检测对象是一个单元格组, 只有在满足所有单元格的 水平和竖直 对齐属性都相同的
* 条件时才会返回其状态值,否则将返回null; 如果当前只检测了一个单元格, 则直接返回当前单元格的对齐状态;
* @param table cell or table cells , 支持单个单元格dom对象 或者 单元格dom对象数组
* @return { align: 'left' || 'right' || 'center', valign: 'top' || 'middle' || 'bottom' } 或者 null
*/
UETable.getTableCellAlignState = function (cells) {
!utils.isArray(cells) && (cells = [cells]);
var result = {},
status = ['align', 'valign'],
tempStatus = null,
isSame = true;//状态是否相同
utils.each(cells, function (cellNode) {
utils.each(status, function (currentState) {
tempStatus = cellNode.getAttribute(currentState);
if (!result[currentState] && tempStatus) {
result[currentState] = tempStatus;
} else if (!result[currentState] || (tempStatus !== result[currentState])) {
isSame = false;
return false;
}
});
return isSame;
});
return isSame ? result : null;
};
/**
* 根据当前选区获取相关的table信息
* @return {Object}
*/
UETable.getTableItemsByRange = function (editor) {
var start = editor.selection.getStart();
//ff下会选中bookmark
if (start && start.id && start.id.indexOf('_baidu_bookmark_start_') === 0 && start.nextSibling) {
start = start.nextSibling;
}
//在table或者td边缘有可能存在选中tr的情况
var cell = start && domUtils.findParentByTagName(start, ["td", "th"], true),
tr = cell && cell.parentNode,
caption = start && domUtils.findParentByTagName(start, 'caption', true),
table = caption ? caption.parentNode : tr && tr.parentNode.parentNode;
return {
cell: cell,
tr: tr,
table: table,
caption: caption
}
};
UETable.getUETableBySelected = function (editor) {
var table = UETable.getTableItemsByRange(editor).table;
if (table && table.ueTable && table.ueTable.selectedTds.length) {
return table.ueTable;
}
return null;
};
UETable.getDefaultValue = function (editor, table) {
var borderMap = {
thin: '0px',
medium: '1px',
thick: '2px'
},
tableBorder, tdPadding, tdBorder, tmpValue;
if (!table) {
table = editor.document.createElement('table');
table.insertRow(0).insertCell(0).innerHTML = 'xxx';
editor.body.appendChild(table);
var td = table.getElementsByTagName('td')[0];
tmpValue = domUtils.getComputedStyle(table, 'border-left-width');
tableBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
tmpValue = domUtils.getComputedStyle(td, 'padding-left');
tdPadding = parseInt(borderMap[tmpValue] || tmpValue, 10);
tmpValue = domUtils.getComputedStyle(td, 'border-left-width');
tdBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
domUtils.remove(table);
return {
tableBorder: tableBorder,
tdPadding: tdPadding,
tdBorder: tdBorder
};
} else {
td = table.getElementsByTagName('td')[0];
tmpValue = domUtils.getComputedStyle(table, 'border-left-width');
tableBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
tmpValue = domUtils.getComputedStyle(td, 'padding-left');
tdPadding = parseInt(borderMap[tmpValue] || tmpValue, 10);
tmpValue = domUtils.getComputedStyle(td, 'border-left-width');
tdBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
return {
tableBorder: tableBorder,
tdPadding: tdPadding,
tdBorder: tdBorder
};
}
};
/**
* 根据当前点击的td或者table获取索引对象
* @param tdOrTable
*/
UETable.getUETable = function (tdOrTable) {
var tag = tdOrTable.tagName.toLowerCase();
tdOrTable = (tag == "td" || tag == "th" || tag == 'caption') ? domUtils.findParentByTagName(tdOrTable, "table", true) : tdOrTable;
if (!tdOrTable.ueTable) {
tdOrTable.ueTable = new UETable(tdOrTable);
}
return tdOrTable.ueTable;
};
UETable.cloneCell = function (cell, ignoreMerge, keepPro) {
if (!cell || utils.isString(cell)) {
return this.table.ownerDocument.createElement(cell || 'td');
}
var flag = domUtils.hasClass(cell, "selectTdClass");
flag && domUtils.removeClasses(cell, "selectTdClass");
var tmpCell = cell.cloneNode(true);
if (ignoreMerge) {
tmpCell.rowSpan = tmpCell.colSpan = 1;
}
//去掉宽高
!keepPro && domUtils.removeAttributes(tmpCell, 'width height');
!keepPro && domUtils.removeAttributes(tmpCell, 'style');
tmpCell.style.borderLeftStyle = "";
tmpCell.style.borderTopStyle = "";
tmpCell.style.borderLeftColor = cell.style.borderRightColor;
tmpCell.style.borderLeftWidth = cell.style.borderRightWidth;
tmpCell.style.borderTopColor = cell.style.borderBottomColor;
tmpCell.style.borderTopWidth = cell.style.borderBottomWidth;
flag && domUtils.addClass(cell, "selectTdClass");
return tmpCell;
}
UETable.prototype = {
getMaxRows: function () {
var rows = this.table.rows, maxLen = 1;
for (var i = 0, row; row = rows[i]; i++) {
var currentMax = 1;
for (var j = 0, cj; cj = row.cells[j++];) {
currentMax = Math.max(cj.rowSpan || 1, currentMax);
}
maxLen = Math.max(currentMax + i, maxLen);
}
return maxLen;
},
/**
* 获取当前表格的最大列数
*/
getMaxCols: function () {
var rows = this.table.rows, maxLen = 0, cellRows = {};
for (var i = 0, row; row = rows[i]; i++) {
var cellsNum = 0;
for (var j = 0, cj; cj = row.cells[j++];) {
cellsNum += (cj.colSpan || 1);
if (cj.rowSpan && cj.rowSpan > 1) {
for (var k = 1; k < cj.rowSpan; k++) {
if (!cellRows['row_' + (i + k)]) {
cellRows['row_' + (i + k)] = (cj.colSpan || 1);
} else {
cellRows['row_' + (i + k)]++
}
}
}
}
cellsNum += cellRows['row_' + i] || 0;
maxLen = Math.max(cellsNum, maxLen);
}
return maxLen;
},
getCellColIndex: function (cell) {
},
/**
* 获取当前cell旁边的单元格,
* @param cell
* @param right
*/
getHSideCell: function (cell, right) {
try {
var cellInfo = this.getCellInfo(cell),
previewRowIndex, previewColIndex;
var len = this.selectedTds.length,
range = this.cellsRange;
//首行或者首列没有前置单元格
if ((!right && (!len ? !cellInfo.colIndex : !range.beginColIndex)) || (right && (!len ? (cellInfo.colIndex == (this.colsNum - 1)) : (range.endColIndex == this.colsNum - 1)))) return null;
previewRowIndex = !len ? cellInfo.rowIndex : range.beginRowIndex;
previewColIndex = !right ? (!len ? (cellInfo.colIndex < 1 ? 0 : (cellInfo.colIndex - 1)) : range.beginColIndex - 1)
: (!len ? cellInfo.colIndex + 1 : range.endColIndex + 1);
return this.getCell(this.indexTable[previewRowIndex][previewColIndex].rowIndex, this.indexTable[previewRowIndex][previewColIndex].cellIndex);
} catch (e) {
showError(e);
}
},
getTabNextCell: function (cell, preRowIndex) {
var cellInfo = this.getCellInfo(cell),
rowIndex = preRowIndex || cellInfo.rowIndex,
colIndex = cellInfo.colIndex + 1 + (cellInfo.colSpan - 1),
nextCell;
try {
nextCell = this.getCell(this.indexTable[rowIndex][colIndex].rowIndex, this.indexTable[rowIndex][colIndex].cellIndex);
} catch (e) {
try {
rowIndex = rowIndex * 1 + 1;
colIndex = 0;
nextCell = this.getCell(this.indexTable[rowIndex][colIndex].rowIndex, this.indexTable[rowIndex][colIndex].cellIndex);
} catch (e) {
}
}
return nextCell;
},
/**
* 获取视觉上的后置单元格
* @param cell
* @param bottom
*/
getVSideCell: function (cell, bottom, ignoreRange) {
try {
var cellInfo = this.getCellInfo(cell),
nextRowIndex, nextColIndex;
var len = this.selectedTds.length && !ignoreRange,
range = this.cellsRange;
//末行或者末列没有后置单元格
if ((!bottom && (cellInfo.rowIndex == 0)) || (bottom && (!len ? (cellInfo.rowIndex + cellInfo.rowSpan > this.rowsNum - 1) : (range.endRowIndex == this.rowsNum - 1)))) return null;
nextRowIndex = !bottom ? (!len ? cellInfo.rowIndex - 1 : range.beginRowIndex - 1)
: (!len ? (cellInfo.rowIndex + cellInfo.rowSpan) : range.endRowIndex + 1);
nextColIndex = !len ? cellInfo.colIndex : range.beginColIndex;
return this.getCell(this.indexTable[nextRowIndex][nextColIndex].rowIndex, this.indexTable[nextRowIndex][nextColIndex].cellIndex);
} catch (e) {
showError(e);
}
},
/**
* 获取相同结束位置的单元格,xOrY指代了是获取x轴相同还是y轴相同
*/
getSameEndPosCells: function (cell, xOrY) {
try {
var flag = (xOrY.toLowerCase() === "x"),
end = domUtils.getXY(cell)[flag ? 'x' : 'y'] + cell["offset" + (flag ? 'Width' : 'Height')],
rows = this.table.rows,
cells = null, returns = [];
for (var i = 0; i < this.rowsNum; i++) {
cells = rows[i].cells;
for (var j = 0, tmpCell; tmpCell = cells[j++];) {
var tmpEnd = domUtils.getXY(tmpCell)[flag ? 'x' : 'y'] + tmpCell["offset" + (flag ? 'Width' : 'Height')];
//对应行的td已经被上面行rowSpan了
if (tmpEnd > end && flag) break;
if (cell == tmpCell || end == tmpEnd) {
//只获取单一的单元格
//todo 仅获取单一单元格在特定情况下会造成returns为空,从而影响后续的拖拽实现,修正这个。需考虑性能
if (tmpCell[flag ? "colSpan" : "rowSpan"] == 1) {
returns.push(tmpCell);
}
if (flag) break;
}
}
}
return returns;
} catch (e) {
showError(e);
}
},
setCellContent: function (cell, content) {
cell.innerHTML = content || (browser.ie ? domUtils.fillChar : " ");
},
cloneCell: UETable.cloneCell,
/**
* 获取跟当前单元格的右边竖线为左边的所有未合并单元格
*/
getSameStartPosXCells: function (cell) {
try {
var start = domUtils.getXY(cell).x + cell.offsetWidth,
rows = this.table.rows, cells, returns = [];
for (var i = 0; i < this.rowsNum; i++) {
cells = rows[i].cells;
for (var j = 0, tmpCell; tmpCell = cells[j++];) {
var tmpStart = domUtils.getXY(tmpCell).x;
if (tmpStart > start) break;
if (tmpStart == start && tmpCell.colSpan == 1) {
returns.push(tmpCell);
break;
}
}
}
return returns;
} catch (e) {
showError(e);
}
},
/**
* 更新table对应的索引表
*/
update: function (table) {
this.table = table || this.table;
this.selectedTds = [];
this.cellsRange = {};
this.indexTable = [];
var rows = this.table.rows,
rowsNum = this.getMaxRows(),
dNum = rowsNum - rows.length,
colsNum = this.getMaxCols();
while (dNum--) {
this.table.insertRow(rows.length);
}
this.rowsNum = rowsNum;
this.colsNum = colsNum;
for (var i = 0, len = rows.length; i < len; i++) {
this.indexTable[i] = new Array(colsNum);
}
//填充索引表
for (var rowIndex = 0, row; row = rows[rowIndex]; rowIndex++) {
for (var cellIndex = 0, cell, cells = row.cells; cell = cells[cellIndex]; cellIndex++) {
//修正整行被rowSpan时导致的行数计算错误
if (cell.rowSpan > rowsNum) {
cell.rowSpan = rowsNum;
}
var colIndex = cellIndex,
rowSpan = cell.rowSpan || 1,
colSpan = cell.colSpan || 1;
//当已经被上一行rowSpan或者被前一列colSpan了,则跳到下一个单元格进行
while (this.indexTable[rowIndex][colIndex]) colIndex++;
for (var j = 0; j < rowSpan; j++) {
for (var k = 0; k < colSpan; k++) {
this.indexTable[rowIndex + j][colIndex + k] = {
rowIndex: rowIndex,
cellIndex: cellIndex,
colIndex: colIndex,
rowSpan: rowSpan,
colSpan: colSpan
}
}
}
}
}
//修复残缺td
for (j = 0; j < rowsNum; j++) {
for (k = 0; k < colsNum; k++) {
if (this.indexTable[j][k] === undefined) {
row = rows[j];
cell = row.cells[row.cells.length - 1];
cell = cell ? cell.cloneNode(true) : this.table.ownerDocument.createElement("td");
this.setCellContent(cell);
if (cell.colSpan !== 1) cell.colSpan = 1;
if (cell.rowSpan !== 1) cell.rowSpan = 1;
row.appendChild(cell);
this.indexTable[j][k] = {
rowIndex: j,
cellIndex: cell.cellIndex,
colIndex: k,
rowSpan: 1,
colSpan: 1
}
}
}
}
//当框选后删除行或者列后撤销,需要重建选区。
var tds = domUtils.getElementsByTagName(this.table, "td"),
selectTds = [];
utils.each(tds, function (td) {
if (domUtils.hasClass(td, "selectTdClass")) {
selectTds.push(td);
}
});
if (selectTds.length) {
var start = selectTds[0],
end = selectTds[selectTds.length - 1],
startInfo = this.getCellInfo(start),
endInfo = this.getCellInfo(end);
this.selectedTds = selectTds;
this.cellsRange = {
beginRowIndex: startInfo.rowIndex,
beginColIndex: startInfo.colIndex,
endRowIndex: endInfo.rowIndex + endInfo.rowSpan - 1,
endColIndex: endInfo.colIndex + endInfo.colSpan - 1
};
}
//给第一行设置firstRow的样式名称,在排序图标的样式上使用到
if (!domUtils.hasClass(this.table.rows[0], "firstRow")) {
domUtils.addClass(this.table.rows[0], "firstRow");
for (var i = 1; i < this.table.rows.length; i++) {
domUtils.removeClasses(this.table.rows[i], "firstRow");
}
}
},
/**
* 获取单元格的索引信息
*/
getCellInfo: function (cell) {
if (!cell) return;
var cellIndex = cell.cellIndex,
rowIndex = cell.parentNode.rowIndex,
rowInfo = this.indexTable[rowIndex],
numCols = this.colsNum;
for (var colIndex = cellIndex; colIndex < numCols; colIndex++) {
var cellInfo = rowInfo[colIndex];
if (cellInfo.rowIndex === rowIndex && cellInfo.cellIndex === cellIndex) {
return cellInfo;
}
}
},
/**
* 根据行列号获取单元格
*/
getCell: function (rowIndex, cellIndex) {
return rowIndex < this.rowsNum && this.table.rows[rowIndex].cells[cellIndex] || null;
},
/**
* 删除单元格
*/
deleteCell: function (cell, rowIndex) {
rowIndex = typeof rowIndex == 'number' ? rowIndex : cell.parentNode.rowIndex;
var row = this.table.rows[rowIndex];
row.deleteCell(cell.cellIndex);
},
/**
* 根据始末两个单元格获取被框选的所有单元格范围
*/
getCellsRange: function (cellA, cellB) {
function checkRange(beginRowIndex, beginColIndex, endRowIndex, endColIndex) {
var tmpBeginRowIndex = beginRowIndex,
tmpBeginColIndex = beginColIndex,
tmpEndRowIndex = endRowIndex,
tmpEndColIndex = endColIndex,
cellInfo, colIndex, rowIndex;
// 通过indexTable检查是否存在超出TableRange上边界的情况
if (beginRowIndex > 0) {
for (colIndex = beginColIndex; colIndex < endColIndex; colIndex++) {
cellInfo = me.indexTable[beginRowIndex][colIndex];
rowIndex = cellInfo.rowIndex;
if (rowIndex < beginRowIndex) {
tmpBeginRowIndex = Math.min(rowIndex, tmpBeginRowIndex);
}
}
}
// 通过indexTable检查是否存在超出TableRange右边界的情况
if (endColIndex < me.colsNum) {
for (rowIndex = beginRowIndex; rowIndex < endRowIndex; rowIndex++) {
cellInfo = me.indexTable[rowIndex][endColIndex];
colIndex = cellInfo.colIndex + cellInfo.colSpan - 1;
if (colIndex > endColIndex) {
tmpEndColIndex = Math.max(colIndex, tmpEndColIndex);
}
}
}
// 检查是否有超出TableRange下边界的情况
if (endRowIndex < me.rowsNum) {
for (colIndex = beginColIndex; colIndex < endColIndex; colIndex++) {
cellInfo = me.indexTable[endRowIndex][colIndex];
rowIndex = cellInfo.rowIndex + cellInfo.rowSpan - 1;
if (rowIndex > endRowIndex) {
tmpEndRowIndex = Math.max(rowIndex, tmpEndRowIndex);
}
}
}
// 检查是否有超出TableRange左边界的情况
if (beginColIndex > 0) {
for (rowIndex = beginRowIndex; rowIndex < endRowIndex; rowIndex++) {
cellInfo = me.indexTable[rowIndex][beginColIndex];
colIndex = cellInfo.colIndex;
if (colIndex < beginColIndex) {
tmpBeginColIndex = Math.min(cellInfo.colIndex, tmpBeginColIndex);
}
}
}
//递归调用直至所有完成所有框选单元格的扩展
if (tmpBeginRowIndex != beginRowIndex || tmpBeginColIndex != beginColIndex || tmpEndRowIndex != endRowIndex || tmpEndColIndex != endColIndex) {
return checkRange(tmpBeginRowIndex, tmpBeginColIndex, tmpEndRowIndex, tmpEndColIndex);
} else {
// 不需要扩展TableRange的情况
return {
beginRowIndex: beginRowIndex,
beginColIndex: beginColIndex,
endRowIndex: endRowIndex,
endColIndex: endColIndex
};
}
}
try {
var me = this,
cellAInfo = me.getCellInfo(cellA);
if (cellA === cellB) {
return {
beginRowIndex: cellAInfo.rowIndex,
beginColIndex: cellAInfo.colIndex,
endRowIndex: cellAInfo.rowIndex + cellAInfo.rowSpan - 1,
endColIndex: cellAInfo.colIndex + cellAInfo.colSpan - 1
};
}
var cellBInfo = me.getCellInfo(cellB);
// 计算TableRange的四个边
var beginRowIndex = Math.min(cellAInfo.rowIndex, cellBInfo.rowIndex),
beginColIndex = Math.min(cellAInfo.colIndex, cellBInfo.colIndex),
endRowIndex = Math.max(cellAInfo.rowIndex + cellAInfo.rowSpan - 1, cellBInfo.rowIndex + cellBInfo.rowSpan - 1),
endColIndex = Math.max(cellAInfo.colIndex + cellAInfo.colSpan - 1, cellBInfo.colIndex + cellBInfo.colSpan - 1);
return checkRange(beginRowIndex, beginColIndex, endRowIndex, endColIndex);
} catch (e) {
//throw e;
}
},
/**
* 依据cellsRange获取对应的单元格集合
*/
getCells: function (range) {
//每次获取cells之前必须先清除上次的选择,否则会对后续获取操作造成影响
this.clearSelected();
var beginRowIndex = range.beginRowIndex,
beginColIndex = range.beginColIndex,
endRowIndex = range.endRowIndex,
endColIndex = range.endColIndex,
cellInfo, rowIndex, colIndex, tdHash = {}, returnTds = [];
for (var i = beginRowIndex; i <= endRowIndex; i++) {
for (var j = beginColIndex; j <= endColIndex; j++) {
cellInfo = this.indexTable[i][j];
rowIndex = cellInfo.rowIndex;
colIndex = cellInfo.colIndex;
// 如果Cells里已经包含了此Cell则跳过
var key = rowIndex + '|' + colIndex;
if (tdHash[key]) continue;
tdHash[key] = 1;
if (rowIndex < i || colIndex < j || rowIndex + cellInfo.rowSpan - 1 > endRowIndex || colIndex + cellInfo.colSpan - 1 > endColIndex) {
return null;
}
returnTds.push(this.getCell(rowIndex, cellInfo.cellIndex));
}
}
return returnTds;
},
/**
* 清理已经选中的单元格
*/
clearSelected: function () {
UETable.removeSelectedClass(this.selectedTds);
this.selectedTds = [];
this.cellsRange = {};
},
/**
* 根据range设置已经选中的单元格
*/
setSelected: function (range) {
var cells = this.getCells(range);
UETable.addSelectedClass(cells);
this.selectedTds = cells;
this.cellsRange = range;
},
isFullRow: function () {
var range = this.cellsRange;
return (range.endColIndex - range.beginColIndex + 1) == this.colsNum;
},
isFullCol: function () {
var range = this.cellsRange,
table = this.table,
ths = table.getElementsByTagName("th"),
rows = range.endRowIndex - range.beginRowIndex + 1;
return !ths.length ? rows == this.rowsNum : rows == this.rowsNum || (rows == this.rowsNum - 1);
},
/**
* 获取视觉上的前置单元格,默认是左边,top传入时
* @param cell
* @param top
*/
getNextCell: function (cell, bottom, ignoreRange) {
try {
var cellInfo = this.getCellInfo(cell),
nextRowIndex, nextColIndex;
var len = this.selectedTds.length && !ignoreRange,
range = this.cellsRange;
//末行或者末列没有后置单元格
if ((!bottom && (cellInfo.rowIndex == 0)) || (bottom && (!len ? (cellInfo.rowIndex + cellInfo.rowSpan > this.rowsNum - 1) : (range.endRowIndex == this.rowsNum - 1)))) return null;
nextRowIndex = !bottom ? (!len ? cellInfo.rowIndex - 1 : range.beginRowIndex - 1)
: (!len ? (cellInfo.rowIndex + cellInfo.rowSpan) : range.endRowIndex + 1);
nextColIndex = !len ? cellInfo.colIndex : range.beginColIndex;
return this.getCell(this.indexTable[nextRowIndex][nextColIndex].rowIndex, this.indexTable[nextRowIndex][nextColIndex].cellIndex);
} catch (e) {
showError(e);
}
},
getPreviewCell: function (cell, top) {
try {
var cellInfo = this.getCellInfo(cell),
previewRowIndex, previewColIndex;
var len = this.selectedTds.length,
range = this.cellsRange;
//首行或者首列没有前置单元格
if ((!top && (!len ? !cellInfo.colIndex : !range.beginColIndex)) || (top && (!len ? (cellInfo.rowIndex > (this.colsNum - 1)) : (range.endColIndex == this.colsNum - 1)))) return null;
previewRowIndex = !top ? (!len ? cellInfo.rowIndex : range.beginRowIndex)
: (!len ? (cellInfo.rowIndex < 1 ? 0 : (cellInfo.rowIndex - 1)) : range.beginRowIndex);
previewColIndex = !top ? (!len ? (cellInfo.colIndex < 1 ? 0 : (cellInfo.colIndex - 1)) : range.beginColIndex - 1)
: (!len ? cellInfo.colIndex : range.endColIndex + 1);
return this.getCell(this.indexTable[previewRowIndex][previewColIndex].rowIndex, this.indexTable[previewRowIndex][previewColIndex].cellIndex);
} catch (e) {
showError(e);
}
},
/**
* 移动单元格中的内容
*/
moveContent: function (cellTo, cellFrom) {
if (UETable.isEmptyBlock(cellFrom)) return;
if (UETable.isEmptyBlock(cellTo)) {
cellTo.innerHTML = cellFrom.innerHTML;
return;
}
var child = cellTo.lastChild;
if (child.nodeType == 3 || !dtd.$block[child.tagName]) {
cellTo.appendChild(cellTo.ownerDocument.createElement('br'))
}
while (child = cellFrom.firstChild) {
cellTo.appendChild(child);
}
},
/**
* 向右合并单元格
*/
mergeRight: function (cell) {
var cellInfo = this.getCellInfo(cell),
rightColIndex = cellInfo.colIndex + cellInfo.colSpan,
rightCellInfo = this.indexTable[cellInfo.rowIndex][rightColIndex],
rightCell = this.getCell(rightCellInfo.rowIndex, rightCellInfo.cellIndex);
//合并
cell.colSpan = cellInfo.colSpan + rightCellInfo.colSpan;
//被合并的单元格不应存在宽度属性
cell.removeAttribute("width");
//移动内容
this.moveContent(cell, rightCell);
//删掉被合并的Cell
this.deleteCell(rightCell, rightCellInfo.rowIndex);
this.update();
},
/**
* 向下合并单元格
*/
mergeDown: function (cell) {
var cellInfo = this.getCellInfo(cell),
downRowIndex = cellInfo.rowIndex + cellInfo.rowSpan,
downCellInfo = this.indexTable[downRowIndex][cellInfo.colIndex],
downCell = this.getCell(downCellInfo.rowIndex, downCellInfo.cellIndex);
cell.rowSpan = cellInfo.rowSpan + downCellInfo.rowSpan;
cell.removeAttribute("height");
this.moveContent(cell, downCell);
this.deleteCell(downCell, downCellInfo.rowIndex);
this.update();
},
/**
* 合并整个range中的内容
*/
mergeRange: function () {
//由于合并操作可以在任意时刻进行,所以无法通过鼠标位置等信息实时生成range,只能通过缓存实例中的cellsRange对象来访问
var range = this.cellsRange,
leftTopCell = this.getCell(range.beginRowIndex, this.indexTable[range.beginRowIndex][range.beginColIndex].cellIndex);
if (leftTopCell.tagName == "TH" && range.endRowIndex !== range.beginRowIndex) {
var index = this.indexTable,
info = this.getCellInfo(leftTopCell);
leftTopCell = this.getCell(1, index[1][info.colIndex].cellIndex);
range = this.getCellsRange(leftTopCell, this.getCell(index[this.rowsNum - 1][info.colIndex].rowIndex, index[this.rowsNum - 1][info.colIndex].cellIndex));
}
// 删除剩余的Cells
var cells = this.getCells(range);
for (var i = 0, ci; ci = cells[i++];) {
if (ci !== leftTopCell) {
this.moveContent(leftTopCell, ci);
this.deleteCell(ci);
}
}
// 修改左上角Cell的rowSpan和colSpan,并调整宽度属性设置
leftTopCell.rowSpan = range.endRowIndex - range.beginRowIndex + 1;
leftTopCell.rowSpan > 1 && leftTopCell.removeAttribute("height");
leftTopCell.colSpan = range.endColIndex - range.beginColIndex + 1;
leftTopCell.colSpan > 1 && leftTopCell.removeAttribute("width");
if (leftTopCell.rowSpan == this.rowsNum && leftTopCell.colSpan != 1) {
leftTopCell.colSpan = 1;
}
if (leftTopCell.colSpan == this.colsNum && leftTopCell.rowSpan != 1) {
var rowIndex = leftTopCell.parentNode.rowIndex;
//解决IE下的表格操作问题
if (this.table.deleteRow) {
for (var i = rowIndex + 1, curIndex = rowIndex + 1, len = leftTopCell.rowSpan; i < len; i++) {
this.table.deleteRow(curIndex);
}
} else {
for (var i = 0, len = leftTopCell.rowSpan - 1; i < len; i++) {
var row = this.table.rows[rowIndex + 1];
row.parentNode.removeChild(row);
}
}
leftTopCell.rowSpan = 1;
}
this.update();
},
/**
* 插入一行单元格
*/
insertRow: function (rowIndex, sourceCell) {
var numCols = this.colsNum,
table = this.table,
row = table.insertRow(rowIndex), cell,
isInsertTitle = typeof sourceCell == 'string' && sourceCell.toUpperCase() == 'TH';
function replaceTdToTh(colIndex, cell, tableRow) {
if (colIndex == 0) {
var tr = tableRow.nextSibling || tableRow.previousSibling,
th = tr.cells[colIndex];
if (th.tagName == 'TH') {
th = cell.ownerDocument.createElement("th");
th.appendChild(cell.firstChild);
tableRow.insertBefore(th, cell);
domUtils.remove(cell)
}
} else {
if (cell.tagName == 'TH') {
var td = cell.ownerDocument.createElement("td");
td.appendChild(cell.firstChild);
tableRow.insertBefore(td, cell);
domUtils.remove(cell)
}
}
}
//首行直接插入,无需考虑部分单元格被rowspan的情况
if (rowIndex == 0 || rowIndex == this.rowsNum) {
for (var colIndex = 0; colIndex < numCols; colIndex++) {
cell = this.cloneCell(sourceCell, true);
this.setCellContent(cell);
cell.getAttribute('vAlign') && cell.setAttribute('vAlign', cell.getAttribute('vAlign'));
row.appendChild(cell);
if (!isInsertTitle) replaceTdToTh(colIndex, cell, row);
}
} else {
var infoRow = this.indexTable[rowIndex],
cellIndex = 0;
for (colIndex = 0; colIndex < numCols; colIndex++) {
var cellInfo = infoRow[colIndex];
//如果存在某个单元格的rowspan穿过待插入行的位置,则修改该单元格的rowspan即可,无需插入单元格
if (cellInfo.rowIndex < rowIndex) {
cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
cell.rowSpan = cellInfo.rowSpan + 1;
} else {
cell = this.cloneCell(sourceCell, true);
this.setCellContent(cell);
row.appendChild(cell);
}
if (!isInsertTitle) replaceTdToTh(colIndex, cell, row);
}
}
//框选时插入不触发contentchange,需要手动更新索引。
this.update();
return row;
},
/**
* 删除一行单元格
* @param rowIndex
*/
deleteRow: function (rowIndex) {
var row = this.table.rows[rowIndex],
infoRow = this.indexTable[rowIndex],
colsNum = this.colsNum,
count = 0; //处理计数
for (var colIndex = 0; colIndex < colsNum;) {
var cellInfo = infoRow[colIndex],
cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
if (cell.rowSpan > 1) {
if (cellInfo.rowIndex == rowIndex) {
var clone = cell.cloneNode(true);
clone.rowSpan = cell.rowSpan - 1;
clone.innerHTML = "";
cell.rowSpan = 1;
var nextRowIndex = rowIndex + 1,
nextRow = this.table.rows[nextRowIndex],
insertCellIndex,
preMerged = this.getPreviewMergedCellsNum(nextRowIndex, colIndex) - count;
if (preMerged < colIndex) {
insertCellIndex = colIndex - preMerged - 1;
//nextRow.insertCell(insertCellIndex);
domUtils.insertAfter(nextRow.cells[insertCellIndex], clone);
} else {
if (nextRow.cells.length) nextRow.insertBefore(clone, nextRow.cells[0])
}
count += 1;
//cell.parentNode.removeChild(cell);
}
}
colIndex += cell.colSpan || 1;
}
var deleteTds = [], cacheMap = {};
for (colIndex = 0; colIndex < colsNum; colIndex++) {
var tmpRowIndex = infoRow[colIndex].rowIndex,
tmpCellIndex = infoRow[colIndex].cellIndex,
key = tmpRowIndex + "_" + tmpCellIndex;
if (cacheMap[key]) continue;
cacheMap[key] = 1;
cell = this.getCell(tmpRowIndex, tmpCellIndex);
deleteTds.push(cell);
}
var mergeTds = [];
utils.each(deleteTds, function (td) {
if (td.rowSpan == 1) {
td.parentNode.removeChild(td);
} else {
mergeTds.push(td);
}
});
utils.each(mergeTds, function (td) {
td.rowSpan--;
});
row.parentNode.removeChild(row);
//浏览器方法本身存在bug,采用自定义方法删除
//this.table.deleteRow(rowIndex);
this.update();
},
insertCol: function (colIndex, sourceCell, defaultValue) {
var rowsNum = this.rowsNum,
rowIndex = 0,
tableRow, cell,
backWidth = parseInt((this.table.offsetWidth - (this.colsNum + 1) * 20 - (this.colsNum + 1)) / (this.colsNum + 1), 10),
isInsertTitleCol = typeof sourceCell == 'string' && sourceCell.toUpperCase() == 'TH';
function replaceTdToTh(rowIndex, cell, tableRow) {
if (rowIndex == 0) {
var th = cell.nextSibling || cell.previousSibling;
if (th.tagName == 'TH') {
th = cell.ownerDocument.createElement("th");
th.appendChild(cell.firstChild);
tableRow.insertBefore(th, cell);
domUtils.remove(cell)
}
} else {
if (cell.tagName == 'TH') {
var td = cell.ownerDocument.createElement("td");
td.appendChild(cell.firstChild);
tableRow.insertBefore(td, cell);
domUtils.remove(cell)
}
}
}
var preCell;
if (colIndex == 0 || colIndex == this.colsNum) {
for (; rowIndex < rowsNum; rowIndex++) {
tableRow = this.table.rows[rowIndex];
preCell = tableRow.cells[colIndex == 0 ? colIndex : tableRow.cells.length];
cell = this.cloneCell(sourceCell, true); //tableRow.insertCell(colIndex == 0 ? colIndex : tableRow.cells.length);
this.setCellContent(cell);
cell.setAttribute('vAlign', cell.getAttribute('vAlign'));
preCell && cell.setAttribute('width', preCell.getAttribute('width'));
if (!colIndex) {
tableRow.insertBefore(cell, tableRow.cells[0]);
} else {
domUtils.insertAfter(tableRow.cells[tableRow.cells.length - 1], cell);
}
if (!isInsertTitleCol) replaceTdToTh(rowIndex, cell, tableRow)
}
} else {
for (; rowIndex < rowsNum; rowIndex++) {
var cellInfo = this.indexTable[rowIndex][colIndex];
if (cellInfo.colIndex < colIndex) {
cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
cell.colSpan = cellInfo.colSpan + 1;
} else {
tableRow = this.table.rows[rowIndex];
preCell = tableRow.cells[cellInfo.cellIndex];
cell = this.cloneCell(sourceCell, true);//tableRow.insertCell(cellInfo.cellIndex);
this.setCellContent(cell);
cell.setAttribute('vAlign', cell.getAttribute('vAlign'));
preCell && cell.setAttribute('width', preCell.getAttribute('width'));
//防止IE下报错
preCell ? tableRow.insertBefore(cell, preCell) : tableRow.appendChild(cell);
}
if (!isInsertTitleCol) replaceTdToTh(rowIndex, cell, tableRow);
}
}
//框选时插入不触发contentchange,需要手动更新索引
this.update();
this.updateWidth(backWidth, defaultValue || { tdPadding: 10, tdBorder: 1 });
},
updateWidth: function (width, defaultValue) {
var table = this.table,
tmpWidth = UETable.getWidth(table) - defaultValue.tdPadding * 2 - defaultValue.tdBorder + width;
if (tmpWidth < table.ownerDocument.body.offsetWidth) {
table.setAttribute("width", tmpWidth);
return;
}
var tds = domUtils.getElementsByTagName(this.table, "td th");
utils.each(tds, function (td) {
td.setAttribute("width", width);
})
},
deleteCol: function (colIndex) {
var indexTable = this.indexTable,
tableRows = this.table.rows,
backTableWidth = this.table.getAttribute("width"),
backTdWidth = 0,
rowsNum = this.rowsNum,
cacheMap = {};
for (var rowIndex = 0; rowIndex < rowsNum;) {
var infoRow = indexTable[rowIndex],
cellInfo = infoRow[colIndex],
key = cellInfo.rowIndex + '_' + cellInfo.colIndex;
// 跳过已经处理过的Cell
if (cacheMap[key]) continue;
cacheMap[key] = 1;
var cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
if (!backTdWidth) backTdWidth = cell && parseInt(cell.offsetWidth / cell.colSpan, 10).toFixed(0);
// 如果Cell的colSpan大于1, 就修改colSpan, 否则就删掉这个Cell
if (cell.colSpan > 1) {
cell.colSpan--;
} else {
tableRows[rowIndex].deleteCell(cellInfo.cellIndex);
}
rowIndex += cellInfo.rowSpan || 1;
}
this.table.setAttribute("width", backTableWidth - backTdWidth);
this.update();
},
splitToCells: function (cell) {
var me = this,
cells = this.splitToRows(cell);
utils.each(cells, function (cell) {
me.splitToCols(cell);
})
},
splitToRows: function (cell) {
var cellInfo = this.getCellInfo(cell),
rowIndex = cellInfo.rowIndex,
colIndex = cellInfo.colIndex,
results = [];
// 修改Cell的rowSpan
cell.rowSpan = 1;
results.push(cell);
// 补齐单元格
for (var i = rowIndex, endRow = rowIndex + cellInfo.rowSpan; i < endRow; i++) {
if (i == rowIndex) continue;
var tableRow = this.table.rows[i],
tmpCell = tableRow.insertCell(colIndex - this.getPreviewMergedCellsNum(i, colIndex));
tmpCell.colSpan = cellInfo.colSpan;
this.setCellContent(tmpCell);
tmpCell.setAttribute('vAlign', cell.getAttribute('vAlign'));
tmpCell.setAttribute('align', cell.getAttribute('align'));
if (cell.style.cssText) {
tmpCell.style.cssText = cell.style.cssText;
}
results.push(tmpCell);
}
this.update();
return results;
},
getPreviewMergedCellsNum: function (rowIndex, colIndex) {
var indexRow = this.indexTable[rowIndex],
num = 0;
for (var i = 0; i < colIndex;) {
var colSpan = indexRow[i].colSpan,
tmpRowIndex = indexRow[i].rowIndex;
num += (colSpan - (tmpRowIndex == rowIndex ? 1 : 0));
i += colSpan;
}
return num;
},
splitToCols: function (cell) {
var backWidth = (cell.offsetWidth / cell.colSpan - 22).toFixed(0),
cellInfo = this.getCellInfo(cell),
rowIndex = cellInfo.rowIndex,
colIndex = cellInfo.colIndex,
results = [];
// 修改Cell的rowSpan
cell.colSpan = 1;
cell.setAttribute("width", backWidth);
results.push(cell);
// 补齐单元格
for (var j = colIndex, endCol = colIndex + cellInfo.colSpan; j < endCol; j++) {
if (j == colIndex) continue;
var tableRow = this.table.rows[rowIndex],
tmpCell = tableRow.insertCell(this.indexTable[rowIndex][j].cellIndex + 1);
tmpCell.rowSpan = cellInfo.rowSpan;
this.setCellContent(tmpCell);
tmpCell.setAttribute('vAlign', cell.getAttribute('vAlign'));
tmpCell.setAttribute('align', cell.getAttribute('align'));
tmpCell.setAttribute('width', backWidth);
if (cell.style.cssText) {
tmpCell.style.cssText = cell.style.cssText;
}
//处理th的情况
if (cell.tagName == 'TH') {
var th = cell.ownerDocument.createElement('th');
th.appendChild(tmpCell.firstChild);
th.setAttribute('vAlign', cell.getAttribute('vAlign'));
th.rowSpan = tmpCell.rowSpan;
tableRow.insertBefore(th, tmpCell);
domUtils.remove(tmpCell);
}
results.push(tmpCell);
}
this.update();
return results;
},
isLastCell: function (cell, rowsNum, colsNum) {
rowsNum = rowsNum || this.rowsNum;
colsNum = colsNum || this.colsNum;
var cellInfo = this.getCellInfo(cell);
return ((cellInfo.rowIndex + cellInfo.rowSpan) == rowsNum) &&
((cellInfo.colIndex + cellInfo.colSpan) == colsNum);
},
getLastCell: function (cells) {
cells = cells || this.table.getElementsByTagName("td");
var firstInfo = this.getCellInfo(cells[0]);
var me = this, last = cells[0],
tr = last.parentNode,
cellsNum = 0, cols = 0, rows;
utils.each(cells, function (cell) {
if (cell.parentNode == tr) cols += cell.colSpan || 1;
cellsNum += cell.rowSpan * cell.colSpan || 1;
});
rows = cellsNum / cols;
utils.each(cells, function (cell) {
if (me.isLastCell(cell, rows, cols)) {
last = cell;
return false;
}
});
return last;
},
selectRow: function (rowIndex) {
var indexRow = this.indexTable[rowIndex],
start = this.getCell(indexRow[0].rowIndex, indexRow[0].cellIndex),
end = this.getCell(indexRow[this.colsNum - 1].rowIndex, indexRow[this.colsNum - 1].cellIndex),
range = this.getCellsRange(start, end);
this.setSelected(range);
},
selectTable: function () {
var tds = this.table.getElementsByTagName("td"),
range = this.getCellsRange(tds[0], tds[tds.length - 1]);
this.setSelected(range);
},
setBackground: function (cells, value) {
if (typeof value === "string") {
utils.each(cells, function (cell) {
cell.style.backgroundColor = value;
})
} else if (typeof value === "object") {
value = utils.extend({
repeat: true,
colorList: ["#ddd", "#fff"]
}, value);
var rowIndex = this.getCellInfo(cells[0]).rowIndex,
count = 0,
colors = value.colorList,
getColor = function (list, index, repeat) {
return list[index] ? list[index] : repeat ? list[index % list.length] : "";
};
for (var i = 0, cell; cell = cells[i++];) {
var cellInfo = this.getCellInfo(cell);
cell.style.backgroundColor = getColor(colors, ((rowIndex + count) == cellInfo.rowIndex) ? count : ++count, value.repeat);
}
}
},
removeBackground: function (cells) {
utils.each(cells, function (cell) {
cell.style.backgroundColor = "";
})
}
};
function showError(e) {
}
})();
// plugins/table.cmds.js
/**
* Created with JetBrains PhpStorm.
* User: taoqili
* Date: 13-2-20
* Time: 下午6:25
* To change this template use File | Settings | File Templates.
*/
;
(function () {
var UT = UE.UETable,
getTableItemsByRange = function (editor) {
return UT.getTableItemsByRange(editor);
},
getUETableBySelected = function (editor) {
return UT.getUETableBySelected(editor)
},
getDefaultValue = function (editor, table) {
return UT.getDefaultValue(editor, table);
},
getUETable = function (tdOrTable) {
return UT.getUETable(tdOrTable);
};
UE.commands['inserttable'] = {
queryCommandState: function () {
return getTableItemsByRange(this).table ? -1 : 0;
},
execCommand: function (cmd, opt) {
function createTable(opt, tdWidth) {
var html = [],
rowsNum = opt.numRows,
colsNum = opt.numCols;
for (var r = 0; r < rowsNum; r++) {
html.push('');
for (var c = 0; c < colsNum; c++) {
html.push('' + (browser.ie && browser.version < 11 ? domUtils.fillChar : ' ') + ' ')
}
html.push(' ')
}
//禁止指定table-width
return ''
}
if (!opt) {
opt = utils.extend({}, {
numCols: this.options.defaultCols,
numRows: this.options.defaultRows,
tdvalign: this.options.tdvalign
})
}
var me = this;
var range = this.selection.getRange(),
start = range.startContainer,
firstParentBlock = domUtils.findParent(start, function (node) {
return domUtils.isBlockElm(node);
}, true) || me.body;
var defaultValue = getDefaultValue(me),
tableWidth = firstParentBlock.offsetWidth,
tdWidth = Math.floor(tableWidth / opt.numCols - defaultValue.tdPadding * 2 - defaultValue.tdBorder);
//todo其他属性
!opt.tdvalign && (opt.tdvalign = me.options.tdvalign);
me.execCommand("inserthtml", createTable(opt, tdWidth));
}
};
UE.commands['insertparagraphbeforetable'] = {
queryCommandState: function () {
return getTableItemsByRange(this).cell ? 0 : -1;
},
execCommand: function () {
var table = getTableItemsByRange(this).table;
if (table) {
var p = this.document.createElement("p");
p.innerHTML = browser.ie ? ' ' : ' ';
table.parentNode.insertBefore(p, table);
this.selection.getRange().setStart(p, 0).setCursor();
}
}
};
UE.commands['deletetable'] = {
queryCommandState: function () {
var rng = this.selection.getRange();
return domUtils.findParentByTagName(rng.startContainer, 'table', true) ? 0 : -1;
},
execCommand: function (cmd, table) {
var rng = this.selection.getRange();
table = table || domUtils.findParentByTagName(rng.startContainer, 'table', true);
if (table) {
var next = table.nextSibling;
if (!next) {
next = domUtils.createElement(this.document, 'p', {
'innerHTML': browser.ie ? domUtils.fillChar : ' '
});
table.parentNode.insertBefore(next, table);
}
domUtils.remove(table);
rng = this.selection.getRange();
if (next.nodeType == 3) {
rng.setStartBefore(next)
} else {
rng.setStart(next, 0)
}
rng.setCursor(false, true)
this.fireEvent("tablehasdeleted")
}
}
};
UE.commands['cellalign'] = {
queryCommandState: function () {
return getSelectedArr(this).length ? 0 : -1
},
execCommand: function (cmd, align) {
var selectedTds = getSelectedArr(this);
if (selectedTds.length) {
for (var i = 0, ci; ci = selectedTds[i++];) {
ci.setAttribute('align', align);
}
}
}
};
UE.commands['cellvalign'] = {
queryCommandState: function () {
return getSelectedArr(this).length ? 0 : -1;
},
execCommand: function (cmd, valign) {
var selectedTds = getSelectedArr(this);
if (selectedTds.length) {
for (var i = 0, ci; ci = selectedTds[i++];) {
ci.setAttribute('vAlign', valign);
}
}
}
};
UE.commands['insertcaption'] = {
queryCommandState: function () {
var table = getTableItemsByRange(this).table;
if (table) {
return table.getElementsByTagName('caption').length == 0 ? 1 : -1;
}
return -1;
},
execCommand: function () {
var table = getTableItemsByRange(this).table;
if (table) {
var caption = this.document.createElement('caption');
caption.innerHTML = browser.ie ? domUtils.fillChar : ' ';
table.insertBefore(caption, table.firstChild);
var range = this.selection.getRange();
range.setStart(caption, 0).setCursor();
}
}
};
UE.commands['deletecaption'] = {
queryCommandState: function () {
var rng = this.selection.getRange(),
table = domUtils.findParentByTagName(rng.startContainer, 'table');
if (table) {
return table.getElementsByTagName('caption').length == 0 ? -1 : 1;
}
return -1;
},
execCommand: function () {
var rng = this.selection.getRange(),
table = domUtils.findParentByTagName(rng.startContainer, 'table');
if (table) {
domUtils.remove(table.getElementsByTagName('caption')[0]);
var range = this.selection.getRange();
range.setStart(table.rows[0].cells[0], 0).setCursor();
}
}
};
UE.commands['inserttitle'] = {
queryCommandState: function () {
var table = getTableItemsByRange(this).table;
if (table) {
var firstRow = table.rows[0];
return firstRow.cells[firstRow.cells.length - 1].tagName.toLowerCase() != 'th' ? 0 : -1
}
return -1;
},
execCommand: function () {
var table = getTableItemsByRange(this).table;
if (table) {
getUETable(table).insertRow(0, 'th');
}
var th = table.getElementsByTagName('th')[0];
this.selection.getRange().setStart(th, 0).setCursor(false, true);
}
};
UE.commands['deletetitle'] = {
queryCommandState: function () {
var table = getTableItemsByRange(this).table;
if (table) {
var firstRow = table.rows[0];
return firstRow.cells[firstRow.cells.length - 1].tagName.toLowerCase() == 'th' ? 0 : -1
}
return -1;
},
execCommand: function () {
var table = getTableItemsByRange(this).table;
if (table) {
domUtils.remove(table.rows[0])
}
var td = table.getElementsByTagName('td')[0];
this.selection.getRange().setStart(td, 0).setCursor(false, true);
}
};
UE.commands['inserttitlecol'] = {
queryCommandState: function () {
var table = getTableItemsByRange(this).table;
if (table) {
var lastRow = table.rows[table.rows.length - 1];
return lastRow.getElementsByTagName('th').length ? -1 : 0;
}
return -1;
},
execCommand: function (cmd) {
var table = getTableItemsByRange(this).table;
if (table) {
getUETable(table).insertCol(0, 'th');
}
resetTdWidth(table, this);
var th = table.getElementsByTagName('th')[0];
this.selection.getRange().setStart(th, 0).setCursor(false, true);
}
};
UE.commands['deletetitlecol'] = {
queryCommandState: function () {
var table = getTableItemsByRange(this).table;
if (table) {
var lastRow = table.rows[table.rows.length - 1];
return lastRow.getElementsByTagName('th').length ? 0 : -1;
}
return -1;
},
execCommand: function () {
var table = getTableItemsByRange(this).table;
if (table) {
for (var i = 0; i < table.rows.length; i++) {
domUtils.remove(table.rows[i].children[0])
}
}
resetTdWidth(table, this);
var td = table.getElementsByTagName('td')[0];
this.selection.getRange().setStart(td, 0).setCursor(false, true);
}
};
UE.commands["mergeright"] = {
queryCommandState: function (cmd) {
var tableItems = getTableItemsByRange(this),
table = tableItems.table,
cell = tableItems.cell;
if (!table || !cell) return -1;
var ut = getUETable(table);
if (ut.selectedTds.length) return -1;
var cellInfo = ut.getCellInfo(cell),
rightColIndex = cellInfo.colIndex + cellInfo.colSpan;
if (rightColIndex >= ut.colsNum) return -1; // 如果处于最右边则不能向右合并
var rightCellInfo = ut.indexTable[cellInfo.rowIndex][rightColIndex],
rightCell = table.rows[rightCellInfo.rowIndex].cells[rightCellInfo.cellIndex];
if (!rightCell || cell.tagName != rightCell.tagName) return -1; // TH和TD不能相互合并
// 当且仅当两个Cell的开始列号和结束列号一致时能进行合并
return (rightCellInfo.rowIndex == cellInfo.rowIndex && rightCellInfo.rowSpan == cellInfo.rowSpan) ? 0 : -1;
},
execCommand: function (cmd) {
var rng = this.selection.getRange(),
bk = rng.createBookmark(true);
var cell = getTableItemsByRange(this).cell,
ut = getUETable(cell);
ut.mergeRight(cell);
rng.moveToBookmark(bk).select();
}
};
UE.commands["mergedown"] = {
queryCommandState: function (cmd) {
var tableItems = getTableItemsByRange(this),
table = tableItems.table,
cell = tableItems.cell;
if (!table || !cell) return -1;
var ut = getUETable(table);
if (ut.selectedTds.length) return -1;
var cellInfo = ut.getCellInfo(cell),
downRowIndex = cellInfo.rowIndex + cellInfo.rowSpan;
if (downRowIndex >= ut.rowsNum) return -1; // 如果处于最下边则不能向下合并
var downCellInfo = ut.indexTable[downRowIndex][cellInfo.colIndex],
downCell = table.rows[downCellInfo.rowIndex].cells[downCellInfo.cellIndex];
if (!downCell || cell.tagName != downCell.tagName) return -1; // TH和TD不能相互合并
// 当且仅当两个Cell的开始列号和结束列号一致时能进行合并
return (downCellInfo.colIndex == cellInfo.colIndex && downCellInfo.colSpan == cellInfo.colSpan) ? 0 : -1;
},
execCommand: function () {
var rng = this.selection.getRange(),
bk = rng.createBookmark(true);
var cell = getTableItemsByRange(this).cell,
ut = getUETable(cell);
ut.mergeDown(cell);
rng.moveToBookmark(bk).select();
}
};
UE.commands["mergecells"] = {
queryCommandState: function () {
return getUETableBySelected(this) ? 0 : -1;
},
execCommand: function () {
var ut = getUETableBySelected(this);
if (ut && ut.selectedTds.length) {
var cell = ut.selectedTds[0];
ut.mergeRange();
var rng = this.selection.getRange();
if (domUtils.isEmptyBlock(cell)) {
rng.setStart(cell, 0).collapse(true)
} else {
rng.selectNodeContents(cell)
}
rng.select();
}
}
};
UE.commands["insertrow"] = {
queryCommandState: function () {
var tableItems = getTableItemsByRange(this),
cell = tableItems.cell;
return cell && (cell.tagName == "TD" || (cell.tagName == 'TH' && tableItems.tr !== tableItems.table.rows[0])) &&
getUETable(tableItems.table).rowsNum < this.options.maxRowNum ? 0 : -1;
},
execCommand: function () {
var rng = this.selection.getRange(),
bk = rng.createBookmark(true);
var tableItems = getTableItemsByRange(this),
cell = tableItems.cell,
table = tableItems.table,
ut = getUETable(table),
cellInfo = ut.getCellInfo(cell);
//ut.insertRow(!ut.selectedTds.length ? cellInfo.rowIndex:ut.cellsRange.beginRowIndex,'');
if (!ut.selectedTds.length) {
ut.insertRow(cellInfo.rowIndex, cell);
} else {
var range = ut.cellsRange;
for (var i = 0, len = range.endRowIndex - range.beginRowIndex + 1; i < len; i++) {
ut.insertRow(range.beginRowIndex, cell);
}
}
rng.moveToBookmark(bk).select();
if (table.getAttribute("interlaced") === "enabled") this.fireEvent("interlacetable", table);
}
};
//后插入行
UE.commands["insertrownext"] = {
queryCommandState: function () {
var tableItems = getTableItemsByRange(this),
cell = tableItems.cell;
return cell && (cell.tagName == "TD") && getUETable(tableItems.table).rowsNum < this.options.maxRowNum ? 0 : -1;
},
execCommand: function () {
var rng = this.selection.getRange(),
bk = rng.createBookmark(true);
var tableItems = getTableItemsByRange(this),
cell = tableItems.cell,
table = tableItems.table,
ut = getUETable(table),
cellInfo = ut.getCellInfo(cell);
//ut.insertRow(!ut.selectedTds.length? cellInfo.rowIndex + cellInfo.rowSpan : ut.cellsRange.endRowIndex + 1,'');
if (!ut.selectedTds.length) {
ut.insertRow(cellInfo.rowIndex + cellInfo.rowSpan, cell);
} else {
var range = ut.cellsRange;
for (var i = 0, len = range.endRowIndex - range.beginRowIndex + 1; i < len; i++) {
ut.insertRow(range.endRowIndex + 1, cell);
}
}
rng.moveToBookmark(bk).select();
if (table.getAttribute("interlaced") === "enabled") this.fireEvent("interlacetable", table);
}
};
UE.commands["deleterow"] = {
queryCommandState: function () {
var tableItems = getTableItemsByRange(this);
return tableItems.cell ? 0 : -1;
},
execCommand: function () {
var cell = getTableItemsByRange(this).cell,
ut = getUETable(cell),
cellsRange = ut.cellsRange,
cellInfo = ut.getCellInfo(cell),
preCell = ut.getVSideCell(cell),
nextCell = ut.getVSideCell(cell, true),
rng = this.selection.getRange();
if (utils.isEmptyObject(cellsRange)) {
ut.deleteRow(cellInfo.rowIndex);
} else {
for (var i = cellsRange.beginRowIndex; i < cellsRange.endRowIndex + 1; i++) {
ut.deleteRow(cellsRange.beginRowIndex);
}
}
var table = ut.table;
if (!table.getElementsByTagName('td').length) {
var nextSibling = table.nextSibling;
domUtils.remove(table);
if (nextSibling) {
rng.setStart(nextSibling, 0).setCursor(false, true);
}
} else {
if (cellInfo.rowSpan == 1 || cellInfo.rowSpan == cellsRange.endRowIndex - cellsRange.beginRowIndex + 1) {
if (nextCell || preCell) rng.selectNodeContents(nextCell || preCell).setCursor(false, true);
} else {
var newCell = ut.getCell(cellInfo.rowIndex, ut.indexTable[cellInfo.rowIndex][cellInfo.colIndex].cellIndex);
if (newCell) rng.selectNodeContents(newCell).setCursor(false, true);
}
}
if (table.getAttribute("interlaced") === "enabled") this.fireEvent("interlacetable", table);
}
};
UE.commands["insertcol"] = {
queryCommandState: function (cmd) {
var tableItems = getTableItemsByRange(this),
cell = tableItems.cell;
return cell && (cell.tagName == "TD" || (cell.tagName == 'TH' && cell !== tableItems.tr.cells[0])) &&
getUETable(tableItems.table).colsNum < this.options.maxColNum ? 0 : -1;
},
execCommand: function (cmd) {
var rng = this.selection.getRange(),
bk = rng.createBookmark(true);
if (this.queryCommandState(cmd) == -1) return;
var cell = getTableItemsByRange(this).cell,
ut = getUETable(cell),
cellInfo = ut.getCellInfo(cell);
//ut.insertCol(!ut.selectedTds.length ? cellInfo.colIndex:ut.cellsRange.beginColIndex);
if (!ut.selectedTds.length) {
ut.insertCol(cellInfo.colIndex, cell);
} else {
var range = ut.cellsRange;
for (var i = 0, len = range.endColIndex - range.beginColIndex + 1; i < len; i++) {
ut.insertCol(range.beginColIndex, cell);
}
}
rng.moveToBookmark(bk).select(true);
}
};
UE.commands["insertcolnext"] = {
queryCommandState: function () {
var tableItems = getTableItemsByRange(this),
cell = tableItems.cell;
return cell && getUETable(tableItems.table).colsNum < this.options.maxColNum ? 0 : -1;
},
execCommand: function () {
var rng = this.selection.getRange(),
bk = rng.createBookmark(true);
var cell = getTableItemsByRange(this).cell,
ut = getUETable(cell),
cellInfo = ut.getCellInfo(cell);
//ut.insertCol(!ut.selectedTds.length ? cellInfo.colIndex + cellInfo.colSpan:ut.cellsRange.endColIndex +1);
if (!ut.selectedTds.length) {
ut.insertCol(cellInfo.colIndex + cellInfo.colSpan, cell);
} else {
var range = ut.cellsRange;
for (var i = 0, len = range.endColIndex - range.beginColIndex + 1; i < len; i++) {
ut.insertCol(range.endColIndex + 1, cell);
}
}
rng.moveToBookmark(bk).select();
}
};
UE.commands["deletecol"] = {
queryCommandState: function () {
var tableItems = getTableItemsByRange(this);
return tableItems.cell ? 0 : -1;
},
execCommand: function () {
var cell = getTableItemsByRange(this).cell,
ut = getUETable(cell),
range = ut.cellsRange,
cellInfo = ut.getCellInfo(cell),
preCell = ut.getHSideCell(cell),
nextCell = ut.getHSideCell(cell, true);
if (utils.isEmptyObject(range)) {
ut.deleteCol(cellInfo.colIndex);
} else {
for (var i = range.beginColIndex; i < range.endColIndex + 1; i++) {
ut.deleteCol(range.beginColIndex);
}
}
var table = ut.table,
rng = this.selection.getRange();
if (!table.getElementsByTagName('td').length) {
var nextSibling = table.nextSibling;
domUtils.remove(table);
if (nextSibling) {
rng.setStart(nextSibling, 0).setCursor(false, true);
}
} else {
if (domUtils.inDoc(cell, this.document)) {
rng.setStart(cell, 0).setCursor(false, true);
} else {
if (nextCell && domUtils.inDoc(nextCell, this.document)) {
rng.selectNodeContents(nextCell).setCursor(false, true);
} else {
if (preCell && domUtils.inDoc(preCell, this.document)) {
rng.selectNodeContents(preCell).setCursor(true, true);
}
}
}
}
}
};
UE.commands["splittocells"] = {
queryCommandState: function () {
var tableItems = getTableItemsByRange(this),
cell = tableItems.cell;
if (!cell) return -1;
var ut = getUETable(tableItems.table);
if (ut.selectedTds.length > 0) return -1;
return cell && (cell.colSpan > 1 || cell.rowSpan > 1) ? 0 : -1;
},
execCommand: function () {
var rng = this.selection.getRange(),
bk = rng.createBookmark(true);
var cell = getTableItemsByRange(this).cell,
ut = getUETable(cell);
ut.splitToCells(cell);
rng.moveToBookmark(bk).select();
}
};
UE.commands["splittorows"] = {
queryCommandState: function () {
var tableItems = getTableItemsByRange(this),
cell = tableItems.cell;
if (!cell) return -1;
var ut = getUETable(tableItems.table);
if (ut.selectedTds.length > 0) return -1;
return cell && cell.rowSpan > 1 ? 0 : -1;
},
execCommand: function () {
var rng = this.selection.getRange(),
bk = rng.createBookmark(true);
var cell = getTableItemsByRange(this).cell,
ut = getUETable(cell);
ut.splitToRows(cell);
rng.moveToBookmark(bk).select();
}
};
UE.commands["splittocols"] = {
queryCommandState: function () {
var tableItems = getTableItemsByRange(this),
cell = tableItems.cell;
if (!cell) return -1;
var ut = getUETable(tableItems.table);
if (ut.selectedTds.length > 0) return -1;
return cell && cell.colSpan > 1 ? 0 : -1;
},
execCommand: function () {
var rng = this.selection.getRange(),
bk = rng.createBookmark(true);
var cell = getTableItemsByRange(this).cell,
ut = getUETable(cell);
ut.splitToCols(cell);
rng.moveToBookmark(bk).select();
}
};
UE.commands["adaptbytext"] =
UE.commands["adaptbywindow"] = {
queryCommandState: function () {
return getTableItemsByRange(this).table ? 0 : -1
},
execCommand: function (cmd) {
var tableItems = getTableItemsByRange(this),
table = tableItems.table;
if (table) {
if (cmd == 'adaptbywindow') {
resetTdWidth(table, this);
} else {
var cells = domUtils.getElementsByTagName(table, "td th");
utils.each(cells, function (cell) {
cell.removeAttribute("width");
});
table.removeAttribute("width");
}
}
}
};
//平均分配各列
UE.commands['averagedistributecol'] = {
queryCommandState: function () {
var ut = getUETableBySelected(this);
if (!ut) return -1;
return ut.isFullRow() || ut.isFullCol() ? 0 : -1;
},
execCommand: function (cmd) {
var me = this,
ut = getUETableBySelected(me);
function getAverageWidth() {
var tb = ut.table,
averageWidth, sumWidth = 0, colsNum = 0,
tbAttr = getDefaultValue(me, tb);
if (ut.isFullRow()) {
sumWidth = tb.offsetWidth;
colsNum = ut.colsNum;
} else {
var begin = ut.cellsRange.beginColIndex,
end = ut.cellsRange.endColIndex,
node;
for (var i = begin; i <= end;) {
node = ut.selectedTds[i];
sumWidth += node.offsetWidth;
i += node.colSpan;
colsNum += 1;
}
}
averageWidth = Math.ceil(sumWidth / colsNum) - tbAttr.tdBorder * 2 - tbAttr.tdPadding * 2;
return averageWidth;
}
function setAverageWidth(averageWidth) {
utils.each(domUtils.getElementsByTagName(ut.table, "th"), function (node) {
node.setAttribute("width", "");
});
var cells = ut.isFullRow() ? domUtils.getElementsByTagName(ut.table, "td") : ut.selectedTds;
utils.each(cells, function (node) {
if (node.colSpan == 1) {
node.setAttribute("width", averageWidth);
}
});
}
if (ut && ut.selectedTds.length) {
setAverageWidth(getAverageWidth());
}
}
};
//平均分配各行
UE.commands['averagedistributerow'] = {
queryCommandState: function () {
var ut = getUETableBySelected(this);
if (!ut) return -1;
if (ut.selectedTds && /th/ig.test(ut.selectedTds[0].tagName)) return -1;
return ut.isFullRow() || ut.isFullCol() ? 0 : -1;
},
execCommand: function (cmd) {
var me = this,
ut = getUETableBySelected(me);
function getAverageHeight() {
var averageHeight, rowNum, sumHeight = 0,
tb = ut.table,
tbAttr = getDefaultValue(me, tb),
tdpadding = parseInt(domUtils.getComputedStyle(tb.getElementsByTagName('td')[0], "padding-top"));
if (ut.isFullCol()) {
var captionArr = domUtils.getElementsByTagName(tb, "caption"),
thArr = domUtils.getElementsByTagName(tb, "th"),
captionHeight, thHeight;
if (captionArr.length > 0) {
captionHeight = captionArr[0].offsetHeight;
}
if (thArr.length > 0) {
thHeight = thArr[0].offsetHeight;
}
sumHeight = tb.offsetHeight - (captionHeight || 0) - (thHeight || 0);
rowNum = thArr.length == 0 ? ut.rowsNum : (ut.rowsNum - 1);
} else {
var begin = ut.cellsRange.beginRowIndex,
end = ut.cellsRange.endRowIndex,
count = 0,
trs = domUtils.getElementsByTagName(tb, "tr");
for (var i = begin; i <= end; i++) {
sumHeight += trs[i].offsetHeight;
count += 1;
}
rowNum = count;
}
//ie8下是混杂模式
if (browser.ie && browser.version < 9) {
averageHeight = Math.ceil(sumHeight / rowNum);
} else {
averageHeight = Math.ceil(sumHeight / rowNum) - tbAttr.tdBorder * 2 - tdpadding * 2;
}
return averageHeight;
}
function setAverageHeight(averageHeight) {
var cells = ut.isFullCol() ? domUtils.getElementsByTagName(ut.table, "td") : ut.selectedTds;
utils.each(cells, function (node) {
if (node.rowSpan == 1) {
node.setAttribute("height", averageHeight);
}
});
}
if (ut && ut.selectedTds.length) {
setAverageHeight(getAverageHeight());
}
}
};
//单元格对齐方式
UE.commands['cellalignment'] = {
queryCommandState: function () {
return getTableItemsByRange(this).table ? 0 : -1
},
execCommand: function (cmd, data) {
var me = this,
ut = getUETableBySelected(me);
if (!ut) {
var start = me.selection.getStart(),
cell = start && domUtils.findParentByTagName(start, ["td", "th", "caption"], true);
if (!/caption/ig.test(cell.tagName)) {
domUtils.setAttributes(cell, data);
} else {
cell.style.textAlign = data.align;
cell.style.verticalAlign = data.vAlign;
}
me.selection.getRange().setCursor(true);
} else {
utils.each(ut.selectedTds, function (cell) {
domUtils.setAttributes(cell, data);
});
}
},
/**
* 查询当前点击的单元格的对齐状态, 如果当前已经选择了多个单元格, 则会返回所有单元格经过统一协调过后的状态
* @see UE.UETable.getTableCellAlignState
*/
queryCommandValue: function (cmd) {
var activeMenuCell = getTableItemsByRange(this).cell;
if (!activeMenuCell) {
activeMenuCell = getSelectedArr(this)[0];
}
if (!activeMenuCell) {
return null;
} else {
//获取同时选中的其他单元格
var cells = UE.UETable.getUETable(activeMenuCell).selectedTds;
!cells.length && (cells = activeMenuCell);
return UE.UETable.getTableCellAlignState(cells);
}
}
};
//表格对齐方式
UE.commands['tablealignment'] = {
queryCommandState: function () {
if (browser.ie && browser.version < 8) {
return -1;
}
return getTableItemsByRange(this).table ? 0 : -1
},
execCommand: function (cmd, value) {
var me = this,
start = me.selection.getStart(),
table = start && domUtils.findParentByTagName(start, ["table"], true);
if (table) {
table.setAttribute("align", value);
}
}
};
//表格属性
UE.commands['edittable'] = {
queryCommandState: function () {
return getTableItemsByRange(this).table ? 0 : -1
},
execCommand: function (cmd, color) {
var rng = this.selection.getRange(),
table = domUtils.findParentByTagName(rng.startContainer, 'table');
if (table) {
var arr = domUtils.getElementsByTagName(table, "td").concat(
domUtils.getElementsByTagName(table, "th"),
domUtils.getElementsByTagName(table, "caption")
);
utils.each(arr, function (node) {
node.style.borderColor = color;
});
}
}
};
//单元格属性
UE.commands['edittd'] = {
queryCommandState: function () {
return getTableItemsByRange(this).table ? 0 : -1
},
execCommand: function (cmd, bkColor) {
var me = this,
ut = getUETableBySelected(me);
if (!ut) {
var start = me.selection.getStart(),
cell = start && domUtils.findParentByTagName(start, ["td", "th", "caption"], true);
if (cell) {
cell.style.backgroundColor = bkColor;
}
} else {
utils.each(ut.selectedTds, function (cell) {
cell.style.backgroundColor = bkColor;
});
}
}
};
UE.commands["settablebackground"] = {
queryCommandState: function () {
return getSelectedArr(this).length > 1 ? 0 : -1;
},
execCommand: function (cmd, value) {
var cells, ut;
cells = getSelectedArr(this);
ut = getUETable(cells[0]);
ut.setBackground(cells, value);
}
};
UE.commands["cleartablebackground"] = {
queryCommandState: function () {
var cells = getSelectedArr(this);
if (!cells.length) return -1;
for (var i = 0, cell; cell = cells[i++];) {
if (cell.style.backgroundColor !== "") return 0;
}
return -1;
},
execCommand: function () {
var cells = getSelectedArr(this),
ut = getUETable(cells[0]);
ut.removeBackground(cells);
}
};
UE.commands["interlacetable"] = UE.commands["uninterlacetable"] = {
queryCommandState: function (cmd) {
var table = getTableItemsByRange(this).table;
if (!table) return -1;
var interlaced = table.getAttribute("interlaced");
if (cmd == "interlacetable") {
//TODO 待定
//是否需要待定,如果设置,则命令只能单次执行成功,但反射具备toggle效果;否则可以覆盖前次命令,但反射将不存在toggle效果
return (interlaced === "enabled") ? -1 : 0;
} else {
return (!interlaced || interlaced === "disabled") ? -1 : 0;
}
},
execCommand: function (cmd, classList) {
var table = getTableItemsByRange(this).table;
if (cmd == "interlacetable") {
table.setAttribute("interlaced", "enabled");
this.fireEvent("interlacetable", table, classList);
} else {
table.setAttribute("interlaced", "disabled");
this.fireEvent("uninterlacetable", table);
}
}
};
UE.commands["setbordervisible"] = {
queryCommandState: function (cmd) {
var table = getTableItemsByRange(this).table;
if (!table) return -1;
return 0;
},
execCommand: function () {
var table = getTableItemsByRange(this).table;
utils.each(domUtils.getElementsByTagName(table, 'td'), function (td) {
td.style.borderWidth = '1px';
td.style.borderStyle = 'solid';
})
}
};
function resetTdWidth(table, editor) {
var tds = domUtils.getElementsByTagName(table, 'td th');
utils.each(tds, function (td) {
td.removeAttribute("width");
});
table.setAttribute('width', getTableWidth(editor, true, getDefaultValue(editor, table)));
var tdsWidths = [];
setTimeout(function () {
utils.each(tds, function (td) {
(td.colSpan == 1) && tdsWidths.push(td.offsetWidth)
})
utils.each(tds, function (td, i) {
(td.colSpan == 1) && td.setAttribute("width", tdsWidths[i] + "");
})
}, 0);
}
function getTableWidth(editor, needIEHack, defaultValue) {
var body = editor.body;
return body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(body, 'margin-left'), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (editor.options.offsetWidth || 0);
}
function getSelectedArr(editor) {
var cell = getTableItemsByRange(editor).cell;
if (cell) {
var ut = getUETable(cell);
return ut.selectedTds.length ? ut.selectedTds : [cell];
} else {
return [];
}
}
})();
// plugins/table.action.js
/**
* Created with JetBrains PhpStorm.
* User: taoqili
* Date: 12-10-12
* Time: 上午10:05
* To change this template use File | Settings | File Templates.
*/
UE.plugins['table'] = function () {
var me = this,
tabTimer = null,
//拖动计时器
tableDragTimer = null,
//双击计时器
tableResizeTimer = null,
//单元格最小宽度
cellMinWidth = 5,
isInResizeBuffer = false,
//单元格边框大小
cellBorderWidth = 5,
//鼠标偏移距离
offsetOfTableCell = 10,
//记录在有限时间内的点击状态, 共有3个取值, 0, 1, 2。 0代表未初始化, 1代表单击了1次,2代表2次
singleClickState = 0,
userActionStatus = null,
//双击允许的时间范围
dblclickTime = 360,
UT = UE.UETable,
getUETable = function (tdOrTable) {
return UT.getUETable(tdOrTable);
},
getUETableBySelected = function (editor) {
return UT.getUETableBySelected(editor);
},
getDefaultValue = function (editor, table) {
return UT.getDefaultValue(editor, table);
},
removeSelectedClass = function (cells) {
return UT.removeSelectedClass(cells);
};
function showError(e) {
// throw e;
}
me.ready(function () {
var me = this;
var orgGetText = me.selection.getText;
me.selection.getText = function () {
var table = getUETableBySelected(me);
if (table) {
var str = '';
utils.each(table.selectedTds, function (td) {
str += td[browser.ie ? 'innerText' : 'textContent'];
})
return str;
} else {
return orgGetText.call(me.selection)
}
}
})
//处理拖动及框选相关方法
var startTd = null, //鼠标按下时的锚点td
currentTd = null, //当前鼠标经过时的td
onDrag = "", //指示当前拖动状态,其值可为"","h","v" ,分别表示未拖动状态,横向拖动状态,纵向拖动状态,用于鼠标移动过程中的判断
onBorder = false, //检测鼠标按下时是否处在单元格边缘位置
dragButton = null,
dragOver = false,
dragLine = null, //模拟的拖动线
dragTd = null; //发生拖动的目标td
var mousedown = false,
//todo 判断混乱模式
needIEHack = true;
me.setOpt({
'maxColNum': 20,
'maxRowNum': 100,
'defaultCols': 5,
'defaultRows': 5,
'tdvalign': 'top',
'cursorpath': me.options.UEDITOR_HOME_URL + "themes/default/images/cursor_",
'tableDragable': false,
'classList': ["ue-table-interlace-color-single", "ue-table-interlace-color-double"]
});
me.getUETable = getUETable;
var commands = {
'deletetable': 1,
'inserttable': 1,
'cellvalign': 1,
'insertcaption': 1,
'deletecaption': 1,
'inserttitle': 1,
'deletetitle': 1,
"mergeright": 1,
"mergedown": 1,
"mergecells": 1,
"insertrow": 1,
"insertrownext": 1,
"deleterow": 1,
"insertcol": 1,
"insertcolnext": 1,
"deletecol": 1,
"splittocells": 1,
"splittorows": 1,
"splittocols": 1,
"adaptbytext": 1,
"adaptbywindow": 1,
"adaptbycustomer": 1,
"insertparagraph": 1,
"insertparagraphbeforetable": 1,
"averagedistributecol": 1,
"averagedistributerow": 1
};
me.ready(function () {
utils.cssRule('table',
//选中的td上的样式
'.selectTdClass{background-color:#edf5fa !important}' +
'table.noBorderTable td,table.noBorderTable th,table.noBorderTable caption{border:1px dashed #ddd !important}' +
//插入的表格的默认样式
'table{margin-bottom:10px;border-collapse:collapse;display:table;}' +
'td,th{padding: 5px 10px;border: 1px solid #DDD;}' +
'caption{border:1px dashed #DDD;border-bottom:0;padding:3px;text-align:center;}' +
'th{border-top:1px solid #BBB;background-color:#F7F7F7;}' +
'table tr.firstRow th{border-top-width:2px;}' +
'.ue-table-interlace-color-single{ background-color: #fcfcfc; } .ue-table-interlace-color-double{ background-color: #f7faff; }' +
'td p{margin:0;padding:0;}', me.document);
var tableCopyList, isFullCol, isFullRow;
//注册del/backspace事件
me.addListener('keydown', function (cmd, evt) {
var me = this;
var keyCode = evt.keyCode || evt.which;
if (keyCode == 8) {
var ut = getUETableBySelected(me);
if (ut && ut.selectedTds.length) {
if (ut.isFullCol()) {
me.execCommand('deletecol')
} else if (ut.isFullRow()) {
me.execCommand('deleterow')
} else {
me.fireEvent('delcells');
}
domUtils.preventDefault(evt);
}
var caption = domUtils.findParentByTagName(me.selection.getStart(), 'caption', true),
range = me.selection.getRange();
if (range.collapsed && caption && isEmptyBlock(caption)) {
me.fireEvent('saveScene');
var table = caption.parentNode;
domUtils.remove(caption);
if (table) {
range.setStart(table.rows[0].cells[0], 0).setCursor(false, true);
}
me.fireEvent('saveScene');
}
}
if (keyCode == 46) {
ut = getUETableBySelected(me);
if (ut) {
me.fireEvent('saveScene');
for (var i = 0, ci; ci = ut.selectedTds[i++];) {
domUtils.fillNode(me.document, ci)
}
me.fireEvent('saveScene');
domUtils.preventDefault(evt);
}
}
if (keyCode == 13) {
var rng = me.selection.getRange(),
caption = domUtils.findParentByTagName(rng.startContainer, 'caption', true);
if (caption) {
var table = domUtils.findParentByTagName(caption, 'table');
if (!rng.collapsed) {
rng.deleteContents();
me.fireEvent('saveScene');
} else {
if (caption) {
rng.setStart(table.rows[0].cells[0], 0).setCursor(false, true);
}
}
domUtils.preventDefault(evt);
return;
}
if (rng.collapsed) {
var table = domUtils.findParentByTagName(rng.startContainer, 'table');
if (table) {
var cell = table.rows[0].cells[0],
start = domUtils.findParentByTagName(me.selection.getStart(), ['td', 'th'], true),
preNode = table.previousSibling;
if (cell === start && (!preNode || preNode.nodeType == 1 && preNode.tagName == 'TABLE') && domUtils.isStartInblock(rng)) {
var first = domUtils.findParent(me.selection.getStart(), function (n) { return domUtils.isBlockElm(n) }, true);
if (first && (/t(h|d)/i.test(first.tagName) || first === start.firstChild)) {
me.execCommand('insertparagraphbeforetable');
domUtils.preventDefault(evt);
}
}
}
}
}
if ((evt.ctrlKey || evt.metaKey) && evt.keyCode == '67') {
tableCopyList = null;
var ut = getUETableBySelected(me);
if (ut) {
var tds = ut.selectedTds;
isFullCol = ut.isFullCol();
isFullRow = ut.isFullRow();
tableCopyList = [
[ut.cloneCell(tds[0], null, true)]
];
for (var i = 1, ci; ci = tds[i]; i++) {
if (ci.parentNode !== tds[i - 1].parentNode) {
tableCopyList.push([ut.cloneCell(ci, null, true)]);
} else {
tableCopyList[tableCopyList.length - 1].push(ut.cloneCell(ci, null, true));
}
}
}
}
});
me.addListener("tablehasdeleted", function () {
toggleDraggableState(this, false, "", null);
if (dragButton) domUtils.remove(dragButton);
});
me.addListener('beforepaste', function (cmd, html) {
var me = this;
var rng = me.selection.getRange();
if (domUtils.findParentByTagName(rng.startContainer, 'caption', true)) {
var div = me.document.createElement("div");
div.innerHTML = html.html;
//trace:3729
html.html = div[browser.ie9below ? 'innerText' : 'textContent'];
return;
}
var table = getUETableBySelected(me);
if (tableCopyList) {
me.fireEvent('saveScene');
var rng = me.selection.getRange();
var td = domUtils.findParentByTagName(rng.startContainer, ['td', 'th'], true), tmpNode, preNode;
if (td) {
var ut = getUETable(td);
if (isFullRow) {
var rowIndex = ut.getCellInfo(td).rowIndex;
if (td.tagName == 'TH') {
rowIndex++;
}
for (var i = 0, ci; ci = tableCopyList[i++];) {
var tr = ut.insertRow(rowIndex++, "td");
for (var j = 0, cj; cj = ci[j]; j++) {
var cell = tr.cells[j];
if (!cell) {
cell = tr.insertCell(j)
}
cell.innerHTML = cj.innerHTML;
cj.getAttribute('width') && cell.setAttribute('width', cj.getAttribute('width'));
cj.getAttribute('vAlign') && cell.setAttribute('vAlign', cj.getAttribute('vAlign'));
cj.getAttribute('align') && cell.setAttribute('align', cj.getAttribute('align'));
cj.style.cssText && (cell.style.cssText = cj.style.cssText)
}
for (var j = 0, cj; cj = tr.cells[j]; j++) {
if (!ci[j])
break;
cj.innerHTML = ci[j].innerHTML;
ci[j].getAttribute('width') && cj.setAttribute('width', ci[j].getAttribute('width'));
ci[j].getAttribute('vAlign') && cj.setAttribute('vAlign', ci[j].getAttribute('vAlign'));
ci[j].getAttribute('align') && cj.setAttribute('align', ci[j].getAttribute('align'));
ci[j].style.cssText && (cj.style.cssText = ci[j].style.cssText)
}
}
} else {
if (isFullCol) {
cellInfo = ut.getCellInfo(td);
var maxColNum = 0;
for (var j = 0, ci = tableCopyList[0], cj; cj = ci[j++];) {
maxColNum += cj.colSpan || 1;
}
me.__hasEnterExecCommand = true;
for (i = 0; i < maxColNum; i++) {
me.execCommand('insertcol');
}
me.__hasEnterExecCommand = false;
td = ut.table.rows[0].cells[cellInfo.cellIndex];
if (td.tagName == 'TH') {
td = ut.table.rows[1].cells[cellInfo.cellIndex];
}
}
for (var i = 0, ci; ci = tableCopyList[i++];) {
tmpNode = td;
for (var j = 0, cj; cj = ci[j++];) {
if (td) {
td.innerHTML = cj.innerHTML;
//todo 定制处理
cj.getAttribute('width') && td.setAttribute('width', cj.getAttribute('width'));
cj.getAttribute('vAlign') && td.setAttribute('vAlign', cj.getAttribute('vAlign'));
cj.getAttribute('align') && td.setAttribute('align', cj.getAttribute('align'));
cj.style.cssText && (td.style.cssText = cj.style.cssText);
preNode = td;
td = td.nextSibling;
} else {
var cloneTd = cj.cloneNode(true);
domUtils.removeAttributes(cloneTd, ['class', 'rowSpan', 'colSpan']);
preNode.parentNode.appendChild(cloneTd)
}
}
td = ut.getNextCell(tmpNode, true, true);
if (!tableCopyList[i])
break;
if (!td) {
var cellInfo = ut.getCellInfo(tmpNode);
ut.table.insertRow(ut.table.rows.length);
ut.update();
td = ut.getVSideCell(tmpNode, true);
}
}
}
ut.update();
} else {
table = me.document.createElement('table');
for (var i = 0, ci; ci = tableCopyList[i++];) {
var tr = table.insertRow(table.rows.length);
for (var j = 0, cj; cj = ci[j++];) {
cloneTd = UT.cloneCell(cj, null, true);
domUtils.removeAttributes(cloneTd, ['class']);
tr.appendChild(cloneTd)
}
if (j == 2 && cloneTd.rowSpan > 1) {
cloneTd.rowSpan = 1;
}
}
var defaultValue = getDefaultValue(me),
width = me.body.offsetWidth -
(needIEHack ? parseInt(domUtils.getComputedStyle(me.body, 'margin-left'), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (me.options.offsetWidth || 0);
me.execCommand('insertHTML', '' + table.innerHTML.replace(/>\s*<').replace(/\bth\b/gi, "td") + '
')
}
me.fireEvent('contentchange');
me.fireEvent('saveScene');
html.html = '';
return true;
} else {
var div = me.document.createElement("div"), tables;
div.innerHTML = html.html;
tables = div.getElementsByTagName("table");
if (domUtils.findParentByTagName(me.selection.getStart(), 'table')) {
utils.each(tables, function (t) {
domUtils.remove(t)
});
if (domUtils.findParentByTagName(me.selection.getStart(), 'caption', true)) {
div.innerHTML = div[browser.ie ? 'innerText' : 'textContent'];
}
} else {
utils.each(tables, function (table) {
removeStyleSize(table, true);
domUtils.removeAttributes(table, ['style', 'border']);
utils.each(domUtils.getElementsByTagName(table, "td"), function (td) {
if (isEmptyBlock(td)) {
domUtils.fillNode(me.document, td);
}
removeStyleSize(td, true);
// domUtils.removeAttributes(td, ['style'])
});
});
}
html.html = div.innerHTML;
}
});
me.addListener('afterpaste', function () {
utils.each(domUtils.getElementsByTagName(me.body, "table"), function (table) {
if (table.offsetWidth > me.body.offsetWidth) {
var defaultValue = getDefaultValue(me, table);
table.style.width = me.body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(me.body, 'margin-left'), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (me.options.offsetWidth || 0) + 'px'
}
})
});
me.addListener('blur', function () {
tableCopyList = null;
});
var timer;
me.addListener('keydown', function () {
clearTimeout(timer);
timer = setTimeout(function () {
var rng = me.selection.getRange(),
cell = domUtils.findParentByTagName(rng.startContainer, ['th', 'td'], true);
if (cell) {
var table = cell.parentNode.parentNode.parentNode;
if (table.offsetWidth > table.getAttribute("width")) {
cell.style.wordBreak = "break-all";
}
}
}, 100);
});
me.addListener("selectionchange", function () {
toggleDraggableState(me, false, "", null);
});
//内容变化时触发索引更新
//todo 可否考虑标记检测,如果不涉及表格的变化就不进行索引重建和更新
me.addListener("contentchange", function () {
var me = this;
//尽可能排除一些不需要更新的状况
hideDragLine(me);
if (getUETableBySelected(me)) return;
var rng = me.selection.getRange();
var start = rng.startContainer;
start = domUtils.findParentByTagName(start, ['td', 'th'], true);
utils.each(domUtils.getElementsByTagName(me.document, 'table'), function (table) {
if (me.fireEvent("excludetable", table) === true) return;
table.ueTable = new UT(table);
//trace:3742
// utils.each(domUtils.getElementsByTagName(me.document, 'td'), function (td) {
//
// if (domUtils.isEmptyBlock(td) && td !== start) {
// domUtils.fillNode(me.document, td);
// if (browser.ie && browser.version == 6) {
// td.innerHTML = ' '
// }
// }
// });
// utils.each(domUtils.getElementsByTagName(me.document, 'th'), function (th) {
// if (domUtils.isEmptyBlock(th) && th !== start) {
// domUtils.fillNode(me.document, th);
// if (browser.ie && browser.version == 6) {
// th.innerHTML = ' '
// }
// }
// });
table.onmouseover = function () {
me.fireEvent('tablemouseover', table);
};
table.onmousemove = function () {
me.fireEvent('tablemousemove', table);
me.options.tableDragable && toggleDragButton(true, this, me);
utils.defer(function () {
me.fireEvent('contentchange', 50)
}, true)
};
table.onmouseout = function () {
me.fireEvent('tablemouseout', table);
toggleDraggableState(me, false, "", null);
hideDragLine(me);
};
table.onclick = function (evt) {
evt = me.window.event || evt;
var target = getParentTdOrTh(evt.target || evt.srcElement);
if (!target) return;
var ut = getUETable(target),
table = ut.table,
cellInfo = ut.getCellInfo(target),
cellsRange,
rng = me.selection.getRange();
// if ("topLeft" == inPosition(table, mouseCoords(evt))) {
// cellsRange = ut.getCellsRange(ut.table.rows[0].cells[0], ut.getLastCell());
// ut.setSelected(cellsRange);
// return;
// }
// if ("bottomRight" == inPosition(table, mouseCoords(evt))) {
//
// return;
// }
if (inTableSide(table, target, evt, true)) {
var endTdCol = ut.getCell(ut.indexTable[ut.rowsNum - 1][cellInfo.colIndex].rowIndex, ut.indexTable[ut.rowsNum - 1][cellInfo.colIndex].cellIndex);
if (evt.shiftKey && ut.selectedTds.length) {
if (ut.selectedTds[0] !== endTdCol) {
cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdCol);
ut.setSelected(cellsRange);
} else {
rng && rng.selectNodeContents(endTdCol).select();
}
} else {
if (target !== endTdCol) {
cellsRange = ut.getCellsRange(target, endTdCol);
ut.setSelected(cellsRange);
} else {
rng && rng.selectNodeContents(endTdCol).select();
}
}
return;
}
if (inTableSide(table, target, evt)) {
var endTdRow = ut.getCell(ut.indexTable[cellInfo.rowIndex][ut.colsNum - 1].rowIndex, ut.indexTable[cellInfo.rowIndex][ut.colsNum - 1].cellIndex);
if (evt.shiftKey && ut.selectedTds.length) {
if (ut.selectedTds[0] !== endTdRow) {
cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdRow);
ut.setSelected(cellsRange);
} else {
rng && rng.selectNodeContents(endTdRow).select();
}
} else {
if (target !== endTdRow) {
cellsRange = ut.getCellsRange(target, endTdRow);
ut.setSelected(cellsRange);
} else {
rng && rng.selectNodeContents(endTdRow).select();
}
}
}
};
});
switchBorderColor(me, true);
});
domUtils.on(me.document, "mousemove", mouseMoveEvent);
domUtils.on(me.document, "mouseout", function (evt) {
var target = evt.target || evt.srcElement;
if (target.tagName == "TABLE") {
toggleDraggableState(me, false, "", null);
}
});
/**
* 表格隔行变色
*/
me.addListener("interlacetable", function (type, table, classList) {
if (!table) return;
var me = this,
rows = table.rows,
len = rows.length,
getClass = function (list, index, repeat) {
return list[index] ? list[index] : repeat ? list[index % list.length] : "";
};
for (var i = 0; i < len; i++) {
rows[i].className = getClass(classList || me.options.classList, i, true);
}
});
me.addListener("uninterlacetable", function (type, table) {
if (!table) return;
var me = this,
rows = table.rows,
classList = me.options.classList,
len = rows.length;
for (var i = 0; i < len; i++) {
domUtils.removeClasses(rows[i], classList);
}
});
me.addListener("mousedown", mouseDownEvent);
me.addListener("mouseup", mouseUpEvent);
//拖动的时候触发mouseup
domUtils.on(me.body, 'dragstart', function (evt) {
mouseUpEvent.call(me, 'dragstart', evt);
});
me.addOutputRule(function (root) {
utils.each(root.getNodesByTagName('div'), function (n) {
if (n.getAttr('id') == 'ue_tableDragLine') {
n.parentNode.removeChild(n);
}
});
});
var currentRowIndex = 0;
me.addListener("mousedown", function () {
currentRowIndex = 0;
});
me.addListener('tabkeydown', function () {
var range = this.selection.getRange(),
common = range.getCommonAncestor(true, true),
table = domUtils.findParentByTagName(common, 'table');
if (table) {
if (domUtils.findParentByTagName(common, 'caption', true)) {
var cell = domUtils.getElementsByTagName(table, 'th td');
if (cell && cell.length) {
range.setStart(cell[0], 0).setCursor(false, true)
}
} else {
var cell = domUtils.findParentByTagName(common, ['td', 'th'], true),
ua = getUETable(cell);
currentRowIndex = cell.rowSpan > 1 ? currentRowIndex : ua.getCellInfo(cell).rowIndex;
var nextCell = ua.getTabNextCell(cell, currentRowIndex);
if (nextCell) {
if (isEmptyBlock(nextCell)) {
range.setStart(nextCell, 0).setCursor(false, true)
} else {
range.selectNodeContents(nextCell).select()
}
} else {
me.fireEvent('saveScene');
me.__hasEnterExecCommand = true;
this.execCommand('insertrownext');
me.__hasEnterExecCommand = false;
range = this.selection.getRange();
range.setStart(table.rows[table.rows.length - 1].cells[0], 0).setCursor();
me.fireEvent('saveScene');
}
}
return true;
}
});
browser.ie && me.addListener('selectionchange', function () {
toggleDraggableState(this, false, "", null);
});
me.addListener("keydown", function (type, evt) {
var me = this;
//处理在表格的最后一个输入tab产生新的表格
var keyCode = evt.keyCode || evt.which;
if (keyCode == 8 || keyCode == 46) {
return;
}
var notCtrlKey = !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey;
notCtrlKey && removeSelectedClass(domUtils.getElementsByTagName(me.body, "td"));
var ut = getUETableBySelected(me);
if (!ut) return;
notCtrlKey && ut.clearSelected();
});
me.addListener("beforegetcontent", function () {
switchBorderColor(this, false);
browser.ie && utils.each(this.document.getElementsByTagName('caption'), function (ci) {
if (domUtils.isEmptyNode(ci)) {
ci.innerHTML = ' '
}
});
});
me.addListener("aftergetcontent", function () {
switchBorderColor(this, true);
});
me.addListener("getAllHtml", function () {
removeSelectedClass(me.document.getElementsByTagName("td"));
});
//修正全屏状态下插入的表格宽度在非全屏状态下撑开编辑器的情况
me.addListener("fullscreenchanged", function (type, fullscreen) {
if (!fullscreen) {
var ratio = this.body.offsetWidth / document.body.offsetWidth,
tables = domUtils.getElementsByTagName(this.body, "table");
utils.each(tables, function (table) {
if (table.offsetWidth < me.body.offsetWidth) return false;
var tds = domUtils.getElementsByTagName(table, "td"),
backWidths = [];
utils.each(tds, function (td) {
backWidths.push(td.offsetWidth);
});
for (var i = 0, td; td = tds[i]; i++) {
td.setAttribute("width", Math.floor(backWidths[i] * ratio));
}
table.setAttribute("width", Math.floor(getTableWidth(me, needIEHack, getDefaultValue(me))))
});
}
});
//重写execCommand命令,用于处理框选时的处理
var oldExecCommand = me.execCommand;
me.execCommand = function (cmd, datatat) {
var me = this,
args = arguments;
cmd = cmd.toLowerCase();
var ut = getUETableBySelected(me), tds,
range = new dom.Range(me.document),
cmdFun = me.commands[cmd] || UE.commands[cmd],
result;
if (!cmdFun) return;
if (ut && !commands[cmd] && !cmdFun.notNeedUndo && !me.__hasEnterExecCommand) {
me.__hasEnterExecCommand = true;
me.fireEvent("beforeexeccommand", cmd);
tds = ut.selectedTds;
var lastState = -2, lastValue = -2, value, state;
for (var i = 0, td; td = tds[i]; i++) {
if (isEmptyBlock(td)) {
range.setStart(td, 0).setCursor(false, true)
} else {
range.selectNode(td).select(true);
}
state = me.queryCommandState(cmd);
value = me.queryCommandValue(cmd);
if (state != -1) {
if (lastState !== state || lastValue !== value) {
me._ignoreContentChange = true;
result = oldExecCommand.apply(me, arguments);
me._ignoreContentChange = false;
}
lastState = me.queryCommandState(cmd);
lastValue = me.queryCommandValue(cmd);
if (domUtils.isEmptyBlock(td)) {
domUtils.fillNode(me.document, td)
}
}
}
range.setStart(tds[0], 0).shrinkBoundary(true).setCursor(false, true);
me.fireEvent('contentchange');
me.fireEvent("afterexeccommand", cmd);
me.__hasEnterExecCommand = false;
me._selectionChange();
} else {
result = oldExecCommand.apply(me, arguments);
}
return result;
};
});
/**
* 删除obj的宽高style,改成属性宽高
* @param obj
* @param replaceToProperty
*/
function removeStyleSize(obj, replaceToProperty) {
removeStyle(obj, "width", true);
removeStyle(obj, "height", true);
}
function removeStyle(obj, styleName, replaceToProperty) {
if (obj.style[styleName]) {
replaceToProperty && obj.setAttribute(styleName, parseInt(obj.style[styleName], 10));
obj.style[styleName] = "";
}
}
function getParentTdOrTh(ele) {
if (ele.tagName == "TD" || ele.tagName == "TH") return ele;
var td;
if (td = domUtils.findParentByTagName(ele, "td", true) || domUtils.findParentByTagName(ele, "th", true)) return td;
return null;
}
function isEmptyBlock(node) {
var reg = new RegExp(domUtils.fillChar, 'g');
if (node[browser.ie ? 'innerText' : 'textContent'].replace(/^\s*$/, '').replace(reg, '').length > 0) {
return 0;
}
for (var n in dtd.$isNotEmpty) {
if (node.getElementsByTagName(n).length) {
return 0;
}
}
return 1;
}
function mouseCoords(evt) {
if (evt.pageX || evt.pageY) {
return { x: evt.pageX, y: evt.pageY };
}
return {
x: evt.clientX + me.document.body.scrollLeft - me.document.body.clientLeft,
y: evt.clientY + me.document.body.scrollTop - me.document.body.clientTop
};
}
function mouseMoveEvent(evt) {
if (isEditorDisabled()) {
return;
}
try {
//普通状态下鼠标移动
var target = getParentTdOrTh(evt.target || evt.srcElement),
pos;
//区分用户的行为是拖动还是双击
if (isInResizeBuffer) {
me.body.style.webkitUserSelect = 'none';
if (Math.abs(userActionStatus.x - evt.clientX) > offsetOfTableCell || Math.abs(userActionStatus.y - evt.clientY) > offsetOfTableCell) {
clearTableDragTimer();
isInResizeBuffer = false;
singleClickState = 0;
//drag action
tableBorderDrag(evt);
}
}
//修改单元格大小时的鼠标移动
if (onDrag && dragTd) {
singleClickState = 0;
me.body.style.webkitUserSelect = 'none';
me.selection.getNative()[browser.ie9below ? 'empty' : 'removeAllRanges']();
pos = mouseCoords(evt);
toggleDraggableState(me, true, onDrag, pos, target);
if (onDrag == "h") {
dragLine.style.left = getPermissionX(dragTd, evt) + "px";
} else if (onDrag == "v") {
dragLine.style.top = getPermissionY(dragTd, evt) + "px";
}
return;
}
//当鼠标处于table上时,修改移动过程中的光标状态
if (target) {
//针对使用table作为容器的组件不触发拖拽效果
if (me.fireEvent('excludetable', target) === true)
return;
pos = mouseCoords(evt);
var state = getRelation(target, pos),
table = domUtils.findParentByTagName(target, "table", true);
if (inTableSide(table, target, evt, true)) {
if (me.fireEvent("excludetable", table) === true) return;
me.body.style.cursor = "url(" + me.options.cursorpath + "h.png),pointer";
} else if (inTableSide(table, target, evt)) {
if (me.fireEvent("excludetable", table) === true) return;
me.body.style.cursor = "url(" + me.options.cursorpath + "v.png),pointer";
} else {
me.body.style.cursor = "text";
var curCell = target;
if (/\d/.test(state)) {
state = state.replace(/\d/, '');
target = getUETable(target).getPreviewCell(target, state == "v");
}
//位于第一行的顶部或者第一列的左边时不可拖动
toggleDraggableState(me, target ? !!state : false, target ? state : '', pos, target);
}
} else {
toggleDragButton(false, table, me);
}
} catch (e) {
showError(e);
}
}
var dragButtonTimer;
function toggleDragButton(show, table, editor) {
if (!show) {
if (dragOver) return;
dragButtonTimer = setTimeout(function () {
!dragOver && dragButton && dragButton.parentNode && dragButton.parentNode.removeChild(dragButton);
}, 2000);
} else {
createDragButton(table, editor);
}
}
function createDragButton(table, editor) {
var pos = domUtils.getXY(table),
doc = table.ownerDocument;
if (dragButton && dragButton.parentNode) return dragButton;
dragButton = doc.createElement("div");
dragButton.contentEditable = false;
dragButton.innerHTML = "";
dragButton.style.cssText = "width:15px;height:15px;background-image:url(" + editor.options.UEDITOR_HOME_URL + "dialogs/table/dragicon.png);position: absolute;cursor:move;top:" + (pos.y - 15) + "px;left:" + (pos.x) + "px;";
domUtils.unSelectable(dragButton);
dragButton.onmouseover = function (evt) {
dragOver = true;
};
dragButton.onmouseout = function (evt) {
dragOver = false;
};
domUtils.on(dragButton, 'click', function (type, evt) {
doClick(evt, this);
});
domUtils.on(dragButton, 'dblclick', function (type, evt) {
doDblClick(evt);
});
domUtils.on(dragButton, 'dragstart', function (type, evt) {
domUtils.preventDefault(evt);
});
var timer;
function doClick(evt, button) {
// 部分浏览器下需要清理
clearTimeout(timer);
timer = setTimeout(function () {
editor.fireEvent("tableClicked", table, button);
}, 300);
}
function doDblClick(evt) {
clearTimeout(timer);
var ut = getUETable(table),
start = table.rows[0].cells[0],
end = ut.getLastCell(),
range = ut.getCellsRange(start, end);
editor.selection.getRange().setStart(start, 0).setCursor(false, true);
ut.setSelected(range);
}
doc.body.appendChild(dragButton);
}
// function inPosition(table, pos) {
// var tablePos = domUtils.getXY(table),
// width = table.offsetWidth,
// height = table.offsetHeight;
// if (pos.x - tablePos.x < 5 && pos.y - tablePos.y < 5) {
// return "topLeft";
// } else if (tablePos.x + width - pos.x < 5 && tablePos.y + height - pos.y < 5) {
// return "bottomRight";
// }
// }
function inTableSide(table, cell, evt, top) {
var pos = mouseCoords(evt),
state = getRelation(cell, pos);
if (top) {
var caption = table.getElementsByTagName("caption")[0],
capHeight = caption ? caption.offsetHeight : 0;
return (state == "v1") && ((pos.y - domUtils.getXY(table).y - capHeight) < 8);
} else {
return (state == "h1") && ((pos.x - domUtils.getXY(table).x) < 8);
}
}
/**
* 获取拖动时允许的X轴坐标
* @param dragTd
* @param evt
*/
function getPermissionX(dragTd, evt) {
var ut = getUETable(dragTd);
if (ut) {
var preTd = ut.getSameEndPosCells(dragTd, "x")[0],
nextTd = ut.getSameStartPosXCells(dragTd)[0],
mouseX = mouseCoords(evt).x,
left = (preTd ? domUtils.getXY(preTd).x : domUtils.getXY(ut.table).x) + 20,
right = nextTd ? domUtils.getXY(nextTd).x + nextTd.offsetWidth - 20 : (me.body.offsetWidth + 5 || parseInt(domUtils.getComputedStyle(me.body, "width"), 10));
left += cellMinWidth;
right -= cellMinWidth;
return mouseX < left ? left : mouseX > right ? right : mouseX;
}
}
/**
* 获取拖动时允许的Y轴坐标
*/
function getPermissionY(dragTd, evt) {
try {
var top = domUtils.getXY(dragTd).y,
mousePosY = mouseCoords(evt).y;
return mousePosY < top ? top : mousePosY;
} catch (e) {
showError(e);
}
}
/**
* 移动状态切换
*/
function toggleDraggableState(editor, draggable, dir, mousePos, cell) {
try {
editor.body.style.cursor = dir == "h" ? "col-resize" : dir == "v" ? "row-resize" : "text";
if (browser.ie) {
if (dir && !mousedown && !getUETableBySelected(editor)) {
getDragLine(editor, editor.document);
showDragLineAt(dir, cell);
} else {
hideDragLine(editor)
}
}
onBorder = draggable;
} catch (e) {
showError(e);
}
}
/**
* 获取与UETable相关的resize line
* @param uetable UETable对象
*/
function getResizeLineByUETable() {
var lineId = '_UETableResizeLine',
line = this.document.getElementById(lineId);
if (!line) {
line = this.document.createElement("div");
line.id = lineId;
line.contnetEditable = false;
line.setAttribute("unselectable", "on");
var styles = {
width: 2 * cellBorderWidth + 1 + 'px',
position: 'absolute',
'z-index': 100000,
cursor: 'col-resize',
background: 'red',
display: 'none'
};
//切换状态
line.onmouseout = function () {
this.style.display = 'none';
};
utils.extend(line.style, styles);
this.document.body.appendChild(line);
}
return line;
}
/**
* 更新resize-line
*/
function updateResizeLine(cell, uetable) {
var line = getResizeLineByUETable.call(this),
table = uetable.table,
styles = {
top: domUtils.getXY(table).y + 'px',
left: domUtils.getXY(cell).x + cell.offsetWidth - cellBorderWidth + 'px',
display: 'block',
height: table.offsetHeight + 'px'
};
utils.extend(line.style, styles);
}
/**
* 显示resize-line
*/
function showResizeLine(cell) {
var uetable = getUETable(cell);
updateResizeLine.call(this, cell, uetable);
}
/**
* 获取鼠标与当前单元格的相对位置
* @param ele
* @param mousePos
*/
function getRelation(ele, mousePos) {
var elePos = domUtils.getXY(ele);
if (!elePos) {
return '';
}
if (elePos.x + ele.offsetWidth - mousePos.x < cellBorderWidth) {
return "h";
}
if (mousePos.x - elePos.x < cellBorderWidth) {
return 'h1'
}
if (elePos.y + ele.offsetHeight - mousePos.y < cellBorderWidth) {
return "v";
}
if (mousePos.y - elePos.y < cellBorderWidth) {
return 'v1'
}
return '';
}
function mouseDownEvent(type, evt) {
if (isEditorDisabled()) {
return;
}
userActionStatus = {
x: evt.clientX,
y: evt.clientY
};
//右键菜单单独处理
if (evt.button == 2) {
var ut = getUETableBySelected(me),
flag = false;
if (ut) {
var td = getTargetTd(me, evt);
utils.each(ut.selectedTds, function (ti) {
if (ti === td) {
flag = true;
}
});
if (!flag) {
removeSelectedClass(domUtils.getElementsByTagName(me.body, "th td"));
ut.clearSelected()
} else {
td = ut.selectedTds[0];
setTimeout(function () {
me.selection.getRange().setStart(td, 0).setCursor(false, true);
}, 0);
}
}
} else {
tableClickHander(evt);
}
}
//清除表格的计时器
function clearTableTimer() {
tabTimer && clearTimeout(tabTimer);
tabTimer = null;
}
//双击收缩
function tableDbclickHandler(evt) {
singleClickState = 0;
evt = evt || me.window.event;
var target = getParentTdOrTh(evt.target || evt.srcElement);
if (target) {
var h;
if (h = getRelation(target, mouseCoords(evt))) {
hideDragLine(me);
if (h == 'h1') {
h = 'h';
if (inTableSide(domUtils.findParentByTagName(target, "table"), target, evt)) {
me.execCommand('adaptbywindow');
} else {
target = getUETable(target).getPreviewCell(target);
if (target) {
var rng = me.selection.getRange();
rng.selectNodeContents(target).setCursor(true, true)
}
}
}
if (h == 'h') {
var ut = getUETable(target),
table = ut.table,
cells = getCellsByMoveBorder(target, table, true);
cells = extractArray(cells, 'left');
ut.width = ut.offsetWidth;
var oldWidth = [],
newWidth = [];
utils.each(cells, function (cell) {
oldWidth.push(cell.offsetWidth);
});
utils.each(cells, function (cell) {
cell.removeAttribute("width");
});
window.setTimeout(function () {
//是否允许改变
var changeable = true;
utils.each(cells, function (cell, index) {
var width = cell.offsetWidth;
if (width > oldWidth[index]) {
changeable = false;
return false;
}
newWidth.push(width);
});
var change = changeable ? newWidth : oldWidth;
utils.each(cells, function (cell, index) {
cell.width = change[index] - getTabcellSpace();
});
}, 0);
// minWidth -= cellMinWidth;
//
// table.removeAttribute("width");
// utils.each(cells, function (cell) {
// cell.style.width = "";
// cell.width -= minWidth;
// });
}
}
}
}
function tableClickHander(evt) {
removeSelectedClass(domUtils.getElementsByTagName(me.body, "td th"));
//trace:3113
//选中单元格,点击table外部,不会清掉table上挂的ueTable,会引起getUETableBySelected方法返回值
utils.each(me.document.getElementsByTagName('table'), function (t) {
t.ueTable = null;
});
startTd = getTargetTd(me, evt);
if (!startTd) return;
var table = domUtils.findParentByTagName(startTd, "table", true);
ut = getUETable(table);
ut && ut.clearSelected();
//判断当前鼠标状态
if (!onBorder) {
me.document.body.style.webkitUserSelect = '';
mousedown = true;
me.addListener('mouseover', mouseOverEvent);
} else {
//边框上的动作处理
borderActionHandler(evt);
}
}
//处理表格边框上的动作, 这里做延时处理,避免两种动作互相影响
function borderActionHandler(evt) {
if (browser.ie) {
evt = reconstruct(evt);
}
clearTableDragTimer();
//是否正在等待resize的缓冲中
isInResizeBuffer = true;
tableDragTimer = setTimeout(function () {
tableBorderDrag(evt);
}, dblclickTime);
}
function extractArray(originArr, key) {
var result = [],
tmp = null;
for (var i = 0, len = originArr.length; i < len; i++) {
tmp = originArr[i][key];
if (tmp) {
result.push(tmp);
}
}
return result;
}
function clearTableDragTimer() {
tableDragTimer && clearTimeout(tableDragTimer);
tableDragTimer = null;
}
function reconstruct(obj) {
var attrs = ['pageX', 'pageY', 'clientX', 'clientY', 'srcElement', 'target'],
newObj = {};
if (obj) {
for (var i = 0, key, val; key = attrs[i]; i++) {
val = obj[key];
val && (newObj[key] = val);
}
}
return newObj;
}
//边框拖动
function tableBorderDrag(evt) {
isInResizeBuffer = false;
startTd = evt.target || evt.srcElement;
if (!startTd) return;
var state = getRelation(startTd, mouseCoords(evt));
if (/\d/.test(state)) {
state = state.replace(/\d/, '');
startTd = getUETable(startTd).getPreviewCell(startTd, state == 'v');
}
hideDragLine(me);
getDragLine(me, me.document);
me.fireEvent('saveScene');
showDragLineAt(state, startTd);
mousedown = true;
//拖动开始
onDrag = state;
dragTd = startTd;
}
function mouseUpEvent(type, evt) {
if (isEditorDisabled()) {
return;
}
clearTableDragTimer();
isInResizeBuffer = false;
if (onBorder) {
singleClickState = ++singleClickState % 3;
userActionStatus = {
x: evt.clientX,
y: evt.clientY
};
tableResizeTimer = setTimeout(function () {
singleClickState > 0 && singleClickState--;
}, dblclickTime);
if (singleClickState === 2) {
singleClickState = 0;
tableDbclickHandler(evt);
return;
}
}
if (evt.button == 2) return;
var me = this;
//清除表格上原生跨选问题
var range = me.selection.getRange(),
start = domUtils.findParentByTagName(range.startContainer, 'table', true),
end = domUtils.findParentByTagName(range.endContainer, 'table', true);
if (start || end) {
if (start === end) {
start = domUtils.findParentByTagName(range.startContainer, ['td', 'th', 'caption'], true);
end = domUtils.findParentByTagName(range.endContainer, ['td', 'th', 'caption'], true);
if (start !== end) {
me.selection.clearRange()
}
} else {
me.selection.clearRange()
}
}
mousedown = false;
me.document.body.style.webkitUserSelect = '';
//拖拽状态下的mouseUP
if (onDrag && dragTd) {
me.selection.getNative()[browser.ie9below ? 'empty' : 'removeAllRanges']();
singleClickState = 0;
dragLine = me.document.getElementById('ue_tableDragLine');
// trace 3973
if (dragLine) {
var dragTdPos = domUtils.getXY(dragTd),
dragLinePos = domUtils.getXY(dragLine);
switch (onDrag) {
case "h":
changeColWidth(dragTd, dragLinePos.x - dragTdPos.x);
break;
case "v":
changeRowHeight(dragTd, dragLinePos.y - dragTdPos.y - dragTd.offsetHeight);
break;
default:
}
onDrag = "";
dragTd = null;
hideDragLine(me);
me.fireEvent('saveScene');
return;
}
}
//正常状态下的mouseup
if (!startTd) {
var target = domUtils.findParentByTagName(evt.target || evt.srcElement, "td", true);
if (!target) target = domUtils.findParentByTagName(evt.target || evt.srcElement, "th", true);
if (target && (target.tagName == "TD" || target.tagName == "TH")) {
if (me.fireEvent("excludetable", target) === true) return;
range = new dom.Range(me.document);
range.setStart(target, 0).setCursor(false, true);
}
} else {
var ut = getUETable(startTd),
cell = ut ? ut.selectedTds[0] : null;
if (cell) {
range = new dom.Range(me.document);
if (domUtils.isEmptyBlock(cell)) {
range.setStart(cell, 0).setCursor(false, true);
} else {
range.selectNodeContents(cell).shrinkBoundary().setCursor(false, true);
}
} else {
range = me.selection.getRange().shrinkBoundary();
if (!range.collapsed) {
var start = domUtils.findParentByTagName(range.startContainer, ['td', 'th'], true),
end = domUtils.findParentByTagName(range.endContainer, ['td', 'th'], true);
//在table里边的不能清除
if (start && !end || !start && end || start && end && start !== end) {
range.setCursor(false, true);
}
}
}
startTd = null;
me.removeListener('mouseover', mouseOverEvent);
}
me._selectionChange(250, evt);
}
function mouseOverEvent(type, evt) {
if (isEditorDisabled()) {
return;
}
var me = this,
tar = evt.target || evt.srcElement;
currentTd = domUtils.findParentByTagName(tar, "td", true) || domUtils.findParentByTagName(tar, "th", true);
//需要判断两个TD是否位于同一个表格内
if (startTd && currentTd &&
((startTd.tagName == "TD" && currentTd.tagName == "TD") || (startTd.tagName == "TH" && currentTd.tagName == "TH")) &&
domUtils.findParentByTagName(startTd, 'table') == domUtils.findParentByTagName(currentTd, 'table')) {
var ut = getUETable(currentTd);
if (startTd != currentTd) {
me.document.body.style.webkitUserSelect = 'none';
me.selection.getNative()[browser.ie9below ? 'empty' : 'removeAllRanges']();
var range = ut.getCellsRange(startTd, currentTd);
ut.setSelected(range);
} else {
me.document.body.style.webkitUserSelect = '';
ut.clearSelected();
}
}
evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
}
function setCellHeight(cell, height, backHeight) {
var lineHight = parseInt(domUtils.getComputedStyle(cell, "line-height"), 10),
tmpHeight = backHeight + height;
height = tmpHeight < lineHight ? lineHight : tmpHeight;
if (cell.style.height) cell.style.height = "";
cell.rowSpan == 1 ? cell.setAttribute("height", height) : (cell.removeAttribute && cell.removeAttribute("height"));
}
function getWidth(cell) {
if (!cell) return 0;
return parseInt(domUtils.getComputedStyle(cell, "width"), 10);
}
function changeColWidth(cell, changeValue) {
var ut = getUETable(cell);
if (ut) {
//根据当前移动的边框获取相关的单元格
var table = ut.table,
cells = getCellsByMoveBorder(cell, table);
table.style.width = "";
table.removeAttribute("width");
//修正改变量
changeValue = correctChangeValue(changeValue, cell, cells);
if (cell.nextSibling) {
var i = 0;
utils.each(cells, function (cellGroup) {
cellGroup.left.width = (+cellGroup.left.width) + changeValue;
cellGroup.right && (cellGroup.right.width = (+cellGroup.right.width) - changeValue);
});
} else {
utils.each(cells, function (cellGroup) {
cellGroup.left.width -= -changeValue;
});
}
}
}
function isEditorDisabled() {
return me.body.contentEditable === "false";
}
function changeRowHeight(td, changeValue) {
if (Math.abs(changeValue) < 10) return;
var ut = getUETable(td);
if (ut) {
var cells = ut.getSameEndPosCells(td, "y"),
//备份需要连带变化的td的原始高度,否则后期无法获取正确的值
backHeight = cells[0] ? cells[0].offsetHeight : 0;
for (var i = 0, cell; cell = cells[i++];) {
setCellHeight(cell, changeValue, backHeight);
}
}
}
/**
* 获取调整单元格大小的相关单元格
* @isContainMergeCell 返回的结果中是否包含发生合并后的单元格
*/
function getCellsByMoveBorder(cell, table, isContainMergeCell) {
if (!table) {
table = domUtils.findParentByTagName(cell, 'table');
}
if (!table) {
return null;
}
//获取到该单元格所在行的序列号
var index = domUtils.getNodeIndex(cell),
temp = cell,
rows = table.rows,
colIndex = 0;
while (temp) {
//获取到当前单元格在未发生单元格合并时的序列
if (temp.nodeType === 1) {
colIndex += (temp.colSpan || 1);
}
temp = temp.previousSibling;
}
temp = null;
//记录想关的单元格
var borderCells = [];
utils.each(rows, function (tabRow) {
var cells = tabRow.cells,
currIndex = 0;
utils.each(cells, function (tabCell) {
currIndex += (tabCell.colSpan || 1);
if (currIndex === colIndex) {
borderCells.push({
left: tabCell,
right: tabCell.nextSibling || null
});
return false;
} else if (currIndex > colIndex) {
if (isContainMergeCell) {
borderCells.push({
left: tabCell
});
}
return false;
}
});
});
return borderCells;
}
/**
* 通过给定的单元格集合获取最小的单元格width
*/
function getMinWidthByTableCells(cells) {
var minWidth = Number.MAX_VALUE;
for (var i = 0, curCell; curCell = cells[i]; i++) {
minWidth = Math.min(minWidth, curCell.width || getTableCellWidth(curCell));
}
return minWidth;
}
function correctChangeValue(changeValue, relatedCell, cells) {
//为单元格的paading预留空间
changeValue -= getTabcellSpace();
if (changeValue < 0) {
return 0;
}
changeValue -= getTableCellWidth(relatedCell);
//确定方向
var direction = changeValue < 0 ? 'left' : 'right';
changeValue = Math.abs(changeValue);
//只关心非最后一个单元格就可以
utils.each(cells, function (cellGroup) {
var curCell = cellGroup[direction];
//为单元格保留最小空间
if (curCell) {
changeValue = Math.min(changeValue, getTableCellWidth(curCell) - cellMinWidth);
}
});
//修正越界
changeValue = changeValue < 0 ? 0 : changeValue;
return direction === 'left' ? -changeValue : changeValue;
}
function getTableCellWidth(cell) {
var width = 0,
//偏移纠正量
offset = 0,
width = cell.offsetWidth - getTabcellSpace();
//最后一个节点纠正一下
if (!cell.nextSibling) {
width -= getTableCellOffset(cell);
}
width = width < 0 ? 0 : width;
try {
cell.width = width;
} catch (e) {
}
return width;
}
/**
* 获取单元格所在表格的最末单元格的偏移量
*/
function getTableCellOffset(cell) {
tab = domUtils.findParentByTagName(cell, "table", false);
if (tab.offsetVal === undefined) {
var prev = cell.previousSibling;
if (prev) {
//最后一个单元格和前一个单元格的width diff结果 如果恰好为一个border width, 则条件成立
tab.offsetVal = cell.offsetWidth - prev.offsetWidth === UT.borderWidth ? UT.borderWidth : 0;
} else {
tab.offsetVal = 0;
}
}
return tab.offsetVal;
}
function getTabcellSpace() {
if (UT.tabcellSpace === undefined) {
var cell = null,
tab = me.document.createElement("table"),
tbody = me.document.createElement("tbody"),
trow = me.document.createElement("tr"),
tabcell = me.document.createElement("td"),
mirror = null;
tabcell.style.cssText = 'border: 0;';
tabcell.width = 1;
trow.appendChild(tabcell);
trow.appendChild(mirror = tabcell.cloneNode(false));
tbody.appendChild(trow);
tab.appendChild(tbody);
tab.style.cssText = "visibility: hidden;";
me.body.appendChild(tab);
UT.paddingSpace = tabcell.offsetWidth - 1;
var tmpTabWidth = tab.offsetWidth;
tabcell.style.cssText = '';
mirror.style.cssText = '';
UT.borderWidth = (tab.offsetWidth - tmpTabWidth) / 3;
UT.tabcellSpace = UT.paddingSpace + UT.borderWidth;
me.body.removeChild(tab);
}
getTabcellSpace = function () { return UT.tabcellSpace; };
return UT.tabcellSpace;
}
function getDragLine(editor, doc) {
if (mousedown) return;
dragLine = editor.document.createElement("div");
domUtils.setAttributes(dragLine, {
id: "ue_tableDragLine",
unselectable: 'on',
contenteditable: false,
'onresizestart': 'return false',
'ondragstart': 'return false',
'onselectstart': 'return false',
style: "background-color:blue;position:absolute;padding:0;margin:0;background-image:none;border:0px none;opacity:0;filter:alpha(opacity=0)"
});
editor.body.appendChild(dragLine);
}
function hideDragLine(editor) {
if (mousedown) return;
var line;
while (line = editor.document.getElementById('ue_tableDragLine')) {
domUtils.remove(line)
}
}
/**
* 依据state(v|h)在cell位置显示横线
* @param state
* @param cell
*/
function showDragLineAt(state, cell) {
if (!cell) return;
var table = domUtils.findParentByTagName(cell, "table"),
caption = table.getElementsByTagName('caption'),
width = table.offsetWidth,
height = table.offsetHeight - (caption.length > 0 ? caption[0].offsetHeight : 0),
tablePos = domUtils.getXY(table),
cellPos = domUtils.getXY(cell), css;
switch (state) {
case "h":
css = 'height:' + height + 'px;top:' + (tablePos.y + (caption.length > 0 ? caption[0].offsetHeight : 0)) + 'px;left:' + (cellPos.x + cell.offsetWidth);
dragLine.style.cssText = css + 'px;position: absolute;display:block;background-color:blue;width:1px;border:0; color:blue;opacity:.3;filter:alpha(opacity=30)';
break;
case "v":
css = 'width:' + width + 'px;left:' + tablePos.x + 'px;top:' + (cellPos.y + cell.offsetHeight);
//必须加上border:0和color:blue,否则低版ie不支持背景色显示
dragLine.style.cssText = css + 'px;overflow:hidden;position: absolute;display:block;background-color:blue;height:1px;border:0;color:blue;opacity:.2;filter:alpha(opacity=20)';
break;
default:
}
}
/**
* 当表格边框颜色为白色时设置为虚线,true为添加虚线
* @param editor
* @param flag
*/
function switchBorderColor(editor, flag) {
var tableArr = domUtils.getElementsByTagName(editor.body, "table"), color;
for (var i = 0, node; node = tableArr[i++];) {
var td = domUtils.getElementsByTagName(node, "td");
if (td[0]) {
if (flag) {
color = (td[0].style.borderColor).replace(/\s/g, "");
if (/(#ffffff)|(rgb\(255,255,255\))/ig.test(color))
domUtils.addClass(node, "noBorderTable")
} else {
domUtils.removeClasses(node, "noBorderTable")
}
}
}
}
function getTableWidth(editor, needIEHack, defaultValue) {
var body = editor.body;
return body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(body, 'margin-left'), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (editor.options.offsetWidth || 0);
}
/**
* 获取当前拖动的单元格
*/
function getTargetTd(editor, evt) {
var target = domUtils.findParentByTagName(evt.target || evt.srcElement, ["td", "th"], true),
dir = null;
if (!target) {
return null;
}
dir = getRelation(target, mouseCoords(evt));
//如果有前一个节点, 需要做一个修正, 否则可能会得到一个错误的td
if (!target) {
return null;
}
if (dir === 'h1' && target.previousSibling) {
var position = domUtils.getXY(target),
cellWidth = target.offsetWidth;
if (Math.abs(position.x + cellWidth - evt.clientX) > cellWidth / 3) {
target = target.previousSibling;
}
} else if (dir === 'v1' && target.parentNode.previousSibling) {
var position = domUtils.getXY(target),
cellHeight = target.offsetHeight;
if (Math.abs(position.y + cellHeight - evt.clientY) > cellHeight / 3) {
target = target.parentNode.previousSibling.firstChild;
}
}
//排除了非td内部以及用于代码高亮部分的td
return target && !(editor.fireEvent("excludetable", target) === true) ? target : null;
}
};
// plugins/table.sort.js
/**
* Created with JetBrains PhpStorm.
* User: Jinqn
* Date: 13-10-12
* Time: 上午10:20
* To change this template use File | Settings | File Templates.
*/
UE.UETable.prototype.sortTable = function (sortByCellIndex, compareFn) {
var table = this.table,
rows = table.rows,
trArray = [],
flag = rows[0].cells[0].tagName === "TH",
lastRowIndex = 0;
if (this.selectedTds.length) {
var range = this.cellsRange,
len = range.endRowIndex + 1;
for (var i = range.beginRowIndex; i < len; i++) {
trArray[i] = rows[i];
}
trArray.splice(0, range.beginRowIndex);
lastRowIndex = (range.endRowIndex + 1) === this.rowsNum ? 0 : range.endRowIndex + 1;
} else {
for (var i = 0, len = rows.length; i < len; i++) {
trArray[i] = rows[i];
}
}
var Fn = {
'reversecurrent': function (td1, td2) {
return 1;
},
'orderbyasc': function (td1, td2) {
var value1 = td1.innerText || td1.textContent,
value2 = td2.innerText || td2.textContent;
return value1.localeCompare(value2);
},
'reversebyasc': function (td1, td2) {
var value1 = td1.innerHTML,
value2 = td2.innerHTML;
return value2.localeCompare(value1);
},
'orderbynum': function (td1, td2) {
var value1 = td1[browser.ie ? 'innerText' : 'textContent'].match(/\d+/),
value2 = td2[browser.ie ? 'innerText' : 'textContent'].match(/\d+/);
if (value1) value1 = +value1[0];
if (value2) value2 = +value2[0];
return (value1 || 0) - (value2 || 0);
},
'reversebynum': function (td1, td2) {
var value1 = td1[browser.ie ? 'innerText' : 'textContent'].match(/\d+/),
value2 = td2[browser.ie ? 'innerText' : 'textContent'].match(/\d+/);
if (value1) value1 = +value1[0];
if (value2) value2 = +value2[0];
return (value2 || 0) - (value1 || 0);
}
};
//对表格设置排序的标记data-sort-type
table.setAttribute('data-sort-type', compareFn && typeof compareFn === "string" && Fn[compareFn] ? compareFn : '');
//th不参与排序
flag && trArray.splice(0, 1);
trArray = utils.sort(trArray, function (tr1, tr2) {
var result;
if (compareFn && typeof compareFn === "function") {
result = compareFn.call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex]);
} else if (compareFn && typeof compareFn === "number") {
result = 1;
} else if (compareFn && typeof compareFn === "string" && Fn[compareFn]) {
result = Fn[compareFn].call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex]);
} else {
result = Fn['orderbyasc'].call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex]);
}
return result;
});
var fragment = table.ownerDocument.createDocumentFragment();
for (var j = 0, len = trArray.length; j < len; j++) {
fragment.appendChild(trArray[j]);
}
var tbody = table.getElementsByTagName("tbody")[0];
if (!lastRowIndex) {
tbody.appendChild(fragment);
} else {
tbody.insertBefore(fragment, rows[lastRowIndex - range.endRowIndex + range.beginRowIndex - 1])
}
};
UE.plugins['tablesort'] = function () {
var me = this,
UT = UE.UETable,
getUETable = function (tdOrTable) {
return UT.getUETable(tdOrTable);
},
getTableItemsByRange = function (editor) {
return UT.getTableItemsByRange(editor);
};
me.ready(function () {
//添加表格可排序的样式
utils.cssRule('tablesort',
'table.sortEnabled tr.firstRow th,table.sortEnabled tr.firstRow td{padding-right:20px;background-repeat: no-repeat;background-position: center right;' +
' background-image:url(' + me.options.themePath + me.options.theme + '/images/sortable.png);}',
me.document);
//做单元格合并操作时,清除可排序标识
me.addListener("afterexeccommand", function (type, cmd) {
if (cmd == 'mergeright' || cmd == 'mergedown' || cmd == 'mergecells') {
this.execCommand('disablesort');
}
});
});
//表格排序
UE.commands['sorttable'] = {
queryCommandState: function () {
var me = this,
tableItems = getTableItemsByRange(me);
if (!tableItems.cell) return -1;
var table = tableItems.table,
cells = table.getElementsByTagName("td");
for (var i = 0, cell; cell = cells[i++];) {
if (cell.rowSpan != 1 || cell.colSpan != 1) return -1;
}
return 0;
},
execCommand: function (cmd, fn) {
var me = this,
range = me.selection.getRange(),
bk = range.createBookmark(true),
tableItems = getTableItemsByRange(me),
cell = tableItems.cell,
ut = getUETable(tableItems.table),
cellInfo = ut.getCellInfo(cell);
ut.sortTable(cellInfo.cellIndex, fn);
range.moveToBookmark(bk);
try {
range.select();
} catch (e) { }
}
};
//设置表格可排序,清除表格可排序
UE.commands["enablesort"] = UE.commands["disablesort"] = {
queryCommandState: function (cmd) {
var table = getTableItemsByRange(this).table;
if (table && cmd == 'enablesort') {
var cells = domUtils.getElementsByTagName(table, 'th td');
for (var i = 0; i < cells.length; i++) {
if (cells[i].getAttribute('colspan') > 1 || cells[i].getAttribute('rowspan') > 1) return -1;
}
}
return !table ? -1 : cmd == 'enablesort' ^ table.getAttribute('data-sort') != 'sortEnabled' ? -1 : 0;
},
execCommand: function (cmd) {
var table = getTableItemsByRange(this).table;
table.setAttribute("data-sort", cmd == "enablesort" ? "sortEnabled" : "sortDisabled");
cmd == "enablesort" ? domUtils.addClass(table, "sortEnabled") : domUtils.removeClasses(table, "sortEnabled");
}
};
};
// plugins/contextmenu.js
///import core
///commands 右键菜单
///commandsName ContextMenu
///commandsTitle 右键菜单
/**
* 右键菜单
* @function
* @name baidu.editor.plugins.contextmenu
* @author zhanyi
*/
UE.plugins['contextmenu'] = function () {
var me = this;
me.setOpt('enableContextMenu', true);
if (me.getOpt('enableContextMenu') === false) {
return;
}
var lang = me.getLang("contextMenu"),
menu,
items = me.options.contextMenu || [
{ label: lang['selectall'], cmdName: 'selectall' },
{
label: lang.cleardoc,
cmdName: 'cleardoc',
exec: function () {
if (confirm(lang.confirmclear)) {
this.execCommand('cleardoc');
}
}
},
'-',
{
label: lang.unlink,
cmdName: 'unlink'
},
'-',
{
group: lang.paragraph,
icon: 'justifyjustify',
subMenu: [
{
label: lang.justifyleft,
cmdName: 'justify',
value: 'left'
},
{
label: lang.justifyright,
cmdName: 'justify',
value: 'right'
},
{
label: lang.justifycenter,
cmdName: 'justify',
value: 'center'
},
{
label: lang.justifyjustify,
cmdName: 'justify',
value: 'justify'
}
]
},
'-',
{
group: lang.table,
icon: 'table',
subMenu: [
{
label: lang.inserttable,
cmdName: 'inserttable'
},
{
label: lang.deletetable,
cmdName: 'deletetable'
},
'-',
{
label: lang.deleterow,
cmdName: 'deleterow'
},
{
label: lang.deletecol,
cmdName: 'deletecol'
},
{
label: lang.insertcol,
cmdName: 'insertcol'
},
{
label: lang.insertcolnext,
cmdName: 'insertcolnext'
},
{
label: lang.insertrow,
cmdName: 'insertrow'
},
{
label: lang.insertrownext,
cmdName: 'insertrownext'
},
'-',
{
label: lang.insertcaption,
cmdName: 'insertcaption'
},
{
label: lang.deletecaption,
cmdName: 'deletecaption'
},
{
label: lang.inserttitle,
cmdName: 'inserttitle'
},
{
label: lang.deletetitle,
cmdName: 'deletetitle'
},
{
label: lang.inserttitlecol,
cmdName: 'inserttitlecol'
},
{
label: lang.deletetitlecol,
cmdName: 'deletetitlecol'
},
'-',
{
label: lang.mergecells,
cmdName: 'mergecells'
},
{
label: lang.mergeright,
cmdName: 'mergeright'
},
{
label: lang.mergedown,
cmdName: 'mergedown'
},
'-',
{
label: lang.splittorows,
cmdName: 'splittorows'
},
{
label: lang.splittocols,
cmdName: 'splittocols'
},
{
label: lang.splittocells,
cmdName: 'splittocells'
},
'-',
{
label: lang.averageDiseRow,
cmdName: 'averagedistributerow'
},
{
label: lang.averageDisCol,
cmdName: 'averagedistributecol'
},
'-',
{
label: lang.edittd,
cmdName: 'edittd',
exec: function () {
if (UE.ui['edittd']) {
new UE.ui['edittd'](this);
}
this.getDialog('edittd').open();
}
},
{
label: lang.edittable,
cmdName: 'edittable',
exec: function () {
if (UE.ui['edittable']) {
new UE.ui['edittable'](this);
}
this.getDialog('edittable').open();
}
},
{
label: lang.setbordervisible,
cmdName: 'setbordervisible'
}
]
},
{
group: lang.tablesort,
icon: 'tablesort',
subMenu: [
{
label: lang.enablesort,
cmdName: 'enablesort'
},
{
label: lang.disablesort,
cmdName: 'disablesort'
},
'-',
{
label: lang.reversecurrent,
cmdName: 'sorttable',
value: 'reversecurrent'
},
{
label: lang.orderbyasc,
cmdName: 'sorttable',
value: 'orderbyasc'
},
{
label: lang.reversebyasc,
cmdName: 'sorttable',
value: 'reversebyasc'
},
{
label: lang.orderbynum,
cmdName: 'sorttable',
value: 'orderbynum'
},
{
label: lang.reversebynum,
cmdName: 'sorttable',
value: 'reversebynum'
}
]
},
{
group: lang.borderbk,
icon: 'borderBack',
subMenu: [
{
label: lang.setcolor,
cmdName: "interlacetable",
exec: function () {
this.execCommand("interlacetable");
}
},
{
label: lang.unsetcolor,
cmdName: "uninterlacetable",
exec: function () {
this.execCommand("uninterlacetable");
}
},
{
label: lang.setbackground,
cmdName: "settablebackground",
exec: function () {
this.execCommand("settablebackground", { repeat: true, colorList: ["#bbb", "#ccc"] });
}
},
{
label: lang.unsetbackground,
cmdName: "cleartablebackground",
exec: function () {
this.execCommand("cleartablebackground");
}
},
{
label: lang.redandblue,
cmdName: "settablebackground",
exec: function () {
this.execCommand("settablebackground", { repeat: true, colorList: ["red", "blue"] });
}
},
{
label: lang.threecolorgradient,
cmdName: "settablebackground",
exec: function () {
this.execCommand("settablebackground", { repeat: true, colorList: ["#aaa", "#bbb", "#ccc"] });
}
}
]
},
{
group: lang.aligntd,
icon: 'aligntd',
subMenu: [
{
cmdName: 'cellalignment',
value: { align: 'left', vAlign: 'top' }
},
{
cmdName: 'cellalignment',
value: { align: 'center', vAlign: 'top' }
},
{
cmdName: 'cellalignment',
value: { align: 'right', vAlign: 'top' }
},
{
cmdName: 'cellalignment',
value: { align: 'left', vAlign: 'middle' }
},
{
cmdName: 'cellalignment',
value: { align: 'center', vAlign: 'middle' }
},
{
cmdName: 'cellalignment',
value: { align: 'right', vAlign: 'middle' }
},
{
cmdName: 'cellalignment',
value: { align: 'left', vAlign: 'bottom' }
},
{
cmdName: 'cellalignment',
value: { align: 'center', vAlign: 'bottom' }
},
{
cmdName: 'cellalignment',
value: { align: 'right', vAlign: 'bottom' }
}
]
},
{
group: lang.aligntable,
icon: 'aligntable',
subMenu: [
{
cmdName: 'tablealignment',
className: 'left',
label: lang.tableleft,
value: "left"
},
{
cmdName: 'tablealignment',
className: 'center',
label: lang.tablecenter,
value: "center"
},
{
cmdName: 'tablealignment',
className: 'right',
label: lang.tableright,
value: "right"
}
]
},
'-',
{
label: lang.insertparagraphbefore,
cmdName: 'insertparagraph',
value: true
},
{
label: lang.insertparagraphafter,
cmdName: 'insertparagraph'
},
{
label: lang['copy'],
cmdName: 'copy'
},
{
label: lang['paste'],
cmdName: 'paste'
}
];
if (!items.length) {
return;
}
var uiUtils = UE.ui.uiUtils;
me.addListener('contextmenu', function (type, evt) {
var offset = uiUtils.getViewportOffsetByEvent(evt);
me.fireEvent('beforeselectionchange');
if (menu) {
menu.destroy();
}
for (var i = 0, ti, contextItems = []; ti = items[i]; i++) {
var last;
(function (item) {
if (item == '-') {
if ((last = contextItems[contextItems.length - 1]) && last !== '-') {
contextItems.push('-');
}
} else if (item.hasOwnProperty("group")) {
for (var j = 0, cj, subMenu = []; cj = item.subMenu[j]; j++) {
(function (subItem) {
if (subItem == '-') {
if ((last = subMenu[subMenu.length - 1]) && last !== '-') {
subMenu.push('-');
} else {
subMenu.splice(subMenu.length - 1);
}
} else {
if ((me.commands[subItem.cmdName] || UE.commands[subItem.cmdName] || subItem.query) &&
(subItem.query ? subItem.query() : me.queryCommandState(subItem.cmdName)) > -1) {
subMenu.push({
'label': subItem.label || me.getLang("contextMenu." + subItem.cmdName + (subItem.value || '')) || "",
'className': 'edui-for-' + subItem.cmdName + (subItem.className ? (' edui-for-' + subItem.cmdName + '-' + subItem.className) : ''),
onclick: subItem.exec ? function () {
subItem.exec.call(me);
} : function () {
me.execCommand(subItem.cmdName, subItem.value);
}
});
}
}
})(cj);
}
if (subMenu.length) {
function getLabel() {
switch (item.icon) {
case "table":
return me.getLang("contextMenu.table");
case "justifyjustify":
return me.getLang("contextMenu.paragraph");
case "aligntd":
return me.getLang("contextMenu.aligntd");
case "aligntable":
return me.getLang("contextMenu.aligntable");
case "tablesort":
return lang.tablesort;
case "borderBack":
return lang.borderbk;
default:
return '';
}
}
contextItems.push({
//todo 修正成自动获取方式
'label': getLabel(),
className: 'edui-for-' + item.icon,
'subMenu': {
items: subMenu,
editor: me
}
});
}
} else {
//有可能commmand没有加载右键不能出来,或者没有command也想能展示出来添加query方法
if ((me.commands[item.cmdName] || UE.commands[item.cmdName] || item.query) &&
(item.query ? item.query.call(me) : me.queryCommandState(item.cmdName)) > -1) {
contextItems.push({
'label': item.label || me.getLang("contextMenu." + item.cmdName),
className: 'edui-for-' + (item.icon ? item.icon : item.cmdName + (item.value || '')),
onclick: item.exec ? function () {
item.exec.call(me);
} : function () {
me.execCommand(item.cmdName, item.value);
}
});
}
}
})(ti);
}
if (contextItems[contextItems.length - 1] == '-') {
contextItems.pop();
}
menu = new UE.ui.Menu({
items: contextItems,
className: "edui-contextmenu",
editor: me
});
menu.render();
menu.showAt(offset);
me.fireEvent("aftershowcontextmenu", menu);
domUtils.preventDefault(evt);
if (browser.ie) {
var ieRange;
try {
ieRange = me.selection.getNative().createRange();
} catch (e) {
return;
}
if (ieRange.item) {
var range = new dom.Range(me.document);
range.selectNode(ieRange.item(0)).select(true, true);
}
}
});
// 添加复制的flash按钮
me.addListener('aftershowcontextmenu', function (type, menu) {
if (me.zeroclipboard) {
var items = menu.items;
for (var key in items) {
if (items[key].className == 'edui-for-copy') {
me.zeroclipboard.clip(items[key].getDom());
}
}
}
});
};
// plugins/shortcutmenu.js
///import core
///commands 弹出菜单
// commandsName popupmenu
///commandsTitle 弹出菜单
/**
* 弹出菜单
* @function
* @name baidu.editor.plugins.popupmenu
* @author xuheng
*/
UE.plugins['shortcutmenu'] = function () {
var me = this,
menu,
items = me.options.shortcutMenu || [];
if (!items.length) {
return;
}
me.addListener('contextmenu mouseup', function (type, e) {
var me = this,
customEvt = {
type: type,
target: e.target || e.srcElement,
screenX: e.screenX,
screenY: e.screenY,
clientX: e.clientX,
clientY: e.clientY
};
setTimeout(function () {
var rng = me.selection.getRange();
if (rng.collapsed === false || type == "contextmenu") {
if (!menu) {
menu = new baidu.editor.ui.ShortCutMenu({
editor: me,
items: items,
theme: me.options.theme,
className: 'edui-shortcutmenu'
});
menu.render();
me.fireEvent("afterrendershortcutmenu", menu);
}
menu.show(customEvt, !!UE.plugins['contextmenu']);
}
});
if (type == 'contextmenu') {
domUtils.preventDefault(e);
if (browser.ie9below) {
var ieRange;
try {
ieRange = me.selection.getNative().createRange();
} catch (e) {
return;
}
if (ieRange.item) {
var range = new dom.Range(me.document);
range.selectNode(ieRange.item(0)).select(true, true);
}
}
}
});
me.addListener('keydown', function (type) {
if (type == "keydown") {
menu && !menu.isHidden && menu.hide();
}
});
};
// plugins/basestyle.js
/**
* B、I、sub、super命令支持
* @file
* @since 1.2.6.1
*/
UE.plugins['basestyle'] = function () {
/**
* 字体加粗
* @command bold
* @param { String } cmd 命令字符串
* @remind 对已加粗的文本内容执行该命令, 将取消加粗
* @method execCommand
* @example
* ```javascript
* //editor是编辑器实例
* //对当前选中的文本内容执行加粗操作
* //第一次执行, 文本内容加粗
* editor.execCommand( 'bold' );
*
* //第二次执行, 文本内容取消加粗
* editor.execCommand( 'bold' );
* ```
*/
/**
* 字体倾斜
* @command italic
* @method execCommand
* @param { String } cmd 命令字符串
* @remind 对已倾斜的文本内容执行该命令, 将取消倾斜
* @example
* ```javascript
* //editor是编辑器实例
* //对当前选中的文本内容执行斜体操作
* //第一次操作, 文本内容将变成斜体
* editor.execCommand( 'italic' );
*
* //再次对同一文本内容执行, 则文本内容将恢复正常
* editor.execCommand( 'italic' );
* ```
*/
/**
* 下标文本,与“superscript”命令互斥
* @command subscript
* @method execCommand
* @remind 把选中的文本内容切换成下标文本, 如果当前选中的文本已经是下标, 则该操作会把文本内容还原成正常文本
* @param { String } cmd 命令字符串
* @example
* ```javascript
* //editor是编辑器实例
* //对当前选中的文本内容执行下标操作
* //第一次操作, 文本内容将变成下标文本
* editor.execCommand( 'subscript' );
*
* //再次对同一文本内容执行, 则文本内容将恢复正常
* editor.execCommand( 'subscript' );
* ```
*/
/**
* 上标文本,与“subscript”命令互斥
* @command superscript
* @method execCommand
* @remind 把选中的文本内容切换成上标文本, 如果当前选中的文本已经是上标, 则该操作会把文本内容还原成正常文本
* @param { String } cmd 命令字符串
* @example
* ```javascript
* //editor是编辑器实例
* //对当前选中的文本内容执行上标操作
* //第一次操作, 文本内容将变成上标文本
* editor.execCommand( 'superscript' );
*
* //再次对同一文本内容执行, 则文本内容将恢复正常
* editor.execCommand( 'superscript' );
* ```
*/
var basestyles = {
'bold': ['strong', 'b'],
'italic': ['em', 'i'],
'subscript': ['sub'],
'superscript': ['sup']
},
getObj = function (editor, tagNames) {
return domUtils.filterNodeList(editor.selection.getStartElementPath(), tagNames);
},
me = this;
//添加快捷键
me.addshortcutkey({
"Bold": "ctrl+66",//^B
"Italic": "ctrl+73", //^I
"Underline": "ctrl+85"//^U
});
me.addInputRule(function (root) {
utils.each(root.getNodesByTagName('b i'), function (node) {
switch (node.tagName) {
case 'b':
node.tagName = 'strong';
break;
case 'i':
node.tagName = 'em';
}
});
});
for (var style in basestyles) {
(function (cmd, tagNames) {
me.commands[cmd] = {
execCommand: function (cmdName) {
var range = me.selection.getRange(), obj = getObj(this, tagNames);
if (range.collapsed) {
if (obj) {
var tmpText = me.document.createTextNode('');
range.insertNode(tmpText).removeInlineStyle(tagNames);
range.setStartBefore(tmpText);
domUtils.remove(tmpText);
} else {
var tmpNode = range.document.createElement(tagNames[0]);
if (cmdName == 'superscript' || cmdName == 'subscript') {
tmpText = me.document.createTextNode('');
range.insertNode(tmpText)
.removeInlineStyle(['sub', 'sup'])
.setStartBefore(tmpText)
.collapse(true);
}
range.insertNode(tmpNode).setStart(tmpNode, 0);
}
range.collapse(true);
} else {
if (cmdName == 'superscript' || cmdName == 'subscript') {
if (!obj || obj.tagName.toLowerCase() != cmdName) {
range.removeInlineStyle(['sub', 'sup']);
}
}
obj ? range.removeInlineStyle(tagNames) : range.applyInlineStyle(tagNames[0]);
}
range.select();
},
queryCommandState: function () {
return getObj(this, tagNames) ? 1 : 0;
}
};
})(style, basestyles[style]);
}
};
// plugins/elementpath.js
/**
* 选取路径命令
* @file
*/
UE.plugins['elementpath'] = function () {
var currentLevel,
tagNames,
me = this;
me.setOpt('elementPathEnabled', true);
if (!me.options.elementPathEnabled) {
return;
}
me.commands['elementpath'] = {
execCommand: function (cmdName, level) {
var start = tagNames[level],
range = me.selection.getRange();
currentLevel = level * 1;
range.selectNode(start).select();
},
queryCommandValue: function () {
//产生一个副本,不能修改原来的startElementPath;
var parents = [].concat(this.selection.getStartElementPath()).reverse(),
names = [];
tagNames = parents;
for (var i = 0, ci; ci = parents[i]; i++) {
if (ci.nodeType == 3) {
continue;
}
var name = ci.tagName.toLowerCase();
if (name == 'img' && ci.getAttribute('anchorname')) {
name = 'anchor';
}
names[i] = name;
if (currentLevel == i) {
currentLevel = -1;
break;
}
}
return names;
}
};
};
// plugins/formatmatch.js
/**
* 格式刷,只格式inline的
* @file
* @since 1.2.6.1
*/
/**
* 格式刷
* @command formatmatch
* @method execCommand
* @remind 该操作不能复制段落格式
* @param { String } cmd 命令字符串
* @example
* ```javascript
* //editor是编辑器实例
* //获取格式刷
* editor.execCommand( 'formatmatch' );
* ```
*/
UE.plugins['formatmatch'] = function () {
var me = this,
list = [], img,
flag = 0;
me.addListener('reset', function () {
list = [];
flag = 0;
});
function addList(type, evt) {
if (browser.webkit) {
var target = evt.target.tagName == 'IMG' ? evt.target : null;
}
function addFormat(range) {
if (text) {
range.selectNode(text);
}
return range.applyInlineStyle(list[list.length - 1].tagName, null, list);
}
me.undoManger && me.undoManger.save();
var range = me.selection.getRange(),
imgT = target || range.getClosedNode();
if (img && imgT && imgT.tagName == 'IMG') {
//trace:964
imgT.style.cssText += ';float:' + (img.style.cssFloat || img.style.styleFloat || 'none') + ';display:' + (img.style.display || 'inline');
img = null;
} else {
if (!img) {
var collapsed = range.collapsed;
if (collapsed) {
var text = me.document.createTextNode('match');
range.insertNode(text).select();
}
me.__hasEnterExecCommand = true;
//不能把block上的属性干掉
//trace:1553
var removeFormatAttributes = me.options.removeFormatAttributes;
me.options.removeFormatAttributes = '';
me.execCommand('removeformat');
me.options.removeFormatAttributes = removeFormatAttributes;
me.__hasEnterExecCommand = false;
//trace:969
range = me.selection.getRange();
if (list.length) {
addFormat(range);
}
if (text) {
range.setStartBefore(text).collapse(true);
}
range.select();
text && domUtils.remove(text);
}
}
me.undoManger && me.undoManger.save();
me.removeListener('mouseup', addList);
flag = 0;
}
me.commands['formatmatch'] = {
execCommand: function (cmdName) {
if (flag) {
flag = 0;
list = [];
me.removeListener('mouseup', addList);
return;
}
var range = me.selection.getRange();
img = range.getClosedNode();
if (!img || img.tagName != 'IMG') {
range.collapse(true).shrinkBoundary();
var start = range.startContainer;
list = domUtils.findParents(start, true, function (node) {
return !domUtils.isBlockElm(node) && node.nodeType == 1;
});
//a不能加入格式刷, 并且克隆节点
for (var i = 0, ci; ci = list[i]; i++) {
if (ci.tagName == 'A') {
list.splice(i, 1);
break;
}
}
}
me.addListener('mouseup', addList);
flag = 1;
},
queryCommandState: function () {
return flag;
},
notNeedUndo: 1
};
};
// plugins/searchreplace.js
///import core
///commands 查找替换
///commandsName SearchReplace
///commandsTitle 查询替换
///commandsDialog dialogs\searchreplace
/**
* @description 查找替换
* @author zhanyi
*/
UE.plugin.register('searchreplace', function () {
var me = this;
var _blockElm = { 'table': 1, 'tbody': 1, 'tr': 1, 'ol': 1, 'ul': 1 };
function findTextInString(textContent, opt, currentIndex) {
var str = opt.searchStr;
if (opt.dir == -1) {
textContent = textContent.split('').reverse().join('');
str = str.split('').reverse().join('');
currentIndex = textContent.length - currentIndex;
}
var reg = new RegExp(str, 'g' + (opt.casesensitive ? '' : 'i')), match;
while (match = reg.exec(textContent)) {
if (match.index >= currentIndex) {
return opt.dir == -1 ? textContent.length - match.index - opt.searchStr.length : match.index;
}
}
return -1
}
function findTextBlockElm(node, currentIndex, opt) {
var textContent, index, methodName = opt.all || opt.dir == 1 ? 'getNextDomNode' : 'getPreDomNode';
if (domUtils.isBody(node)) {
node = node.firstChild;
}
var first = 1;
while (node) {
textContent = node.nodeType == 3 ? node.nodeValue : node[browser.ie ? 'innerText' : 'textContent'];
index = findTextInString(textContent, opt, currentIndex);
first = 0;
if (index != -1) {
return {
'node': node,
'index': index
}
}
node = domUtils[methodName](node);
while (node && _blockElm[node.nodeName.toLowerCase()]) {
node = domUtils[methodName](node, true);
}
if (node) {
currentIndex = opt.dir == -1 ? (node.nodeType == 3 ? node.nodeValue : node[browser.ie ? 'innerText' : 'textContent']).length : 0;
}
}
}
function findNTextInBlockElm(node, index, str) {
var currentIndex = 0,
currentNode = node.firstChild,
currentNodeLength = 0,
result;
while (currentNode) {
if (currentNode.nodeType == 3) {
currentNodeLength = currentNode.nodeValue.replace(/(^[\t\r\n]+)|([\t\r\n]+$)/, '').length;
currentIndex += currentNodeLength;
if (currentIndex >= index) {
return {
'node': currentNode,
'index': currentNodeLength - (currentIndex - index)
}
}
} else if (!dtd.$empty[currentNode.tagName]) {
currentNodeLength = currentNode[browser.ie ? 'innerText' : 'textContent'].replace(/(^[\t\r\n]+)|([\t\r\n]+$)/, '').length
currentIndex += currentNodeLength;
if (currentIndex >= index) {
result = findNTextInBlockElm(currentNode, currentNodeLength - (currentIndex - index), str);
if (result) {
return result;
}
}
}
currentNode = domUtils.getNextDomNode(currentNode);
}
}
function searchReplace(me, opt) {
var rng = me.selection.getRange(),
startBlockNode,
searchStr = opt.searchStr,
span = me.document.createElement('span');
span.innerHTML = '$$ueditor_searchreplace_key$$';
rng.shrinkBoundary(true);
//判断是不是第一次选中
if (!rng.collapsed) {
rng.select();
var rngText = me.selection.getText();
if (new RegExp('^' + opt.searchStr + '$', (opt.casesensitive ? '' : 'i')).test(rngText)) {
if (opt.replaceStr != undefined) {
replaceText(rng, opt.replaceStr);
rng.select();
return true;
} else {
rng.collapse(opt.dir == -1)
}
}
}
rng.insertNode(span);
rng.enlargeToBlockElm(true);
startBlockNode = rng.startContainer;
var currentIndex = startBlockNode[browser.ie ? 'innerText' : 'textContent'].indexOf('$$ueditor_searchreplace_key$$');
rng.setStartBefore(span);
domUtils.remove(span);
var result = findTextBlockElm(startBlockNode, currentIndex, opt);
if (result) {
var rngStart = findNTextInBlockElm(result.node, result.index, searchStr);
var rngEnd = findNTextInBlockElm(result.node, result.index + searchStr.length, searchStr);
rng.setStart(rngStart.node, rngStart.index).setEnd(rngEnd.node, rngEnd.index);
if (opt.replaceStr !== undefined) {
replaceText(rng, opt.replaceStr)
}
rng.select();
return true;
} else {
rng.setCursor()
}
}
function replaceText(rng, str) {
str = me.document.createTextNode(str);
rng.deleteContents().insertNode(str);
}
return {
commands: {
'searchreplace': {
execCommand: function (cmdName, opt) {
utils.extend(opt, {
all: false,
casesensitive: false,
dir: 1
}, true);
var num = 0;
if (opt.all) {
var rng = me.selection.getRange(),
first = me.body.firstChild;
if (first && first.nodeType == 1) {
rng.setStart(first, 0);
rng.shrinkBoundary(true);
} else if (first.nodeType == 3) {
rng.setStartBefore(first)
}
rng.collapse(true).select(true);
if (opt.replaceStr !== undefined) {
me.fireEvent('saveScene');
}
while (searchReplace(this, opt)) {
num++;
}
if (num) {
me.fireEvent('saveScene');
}
} else {
if (opt.replaceStr !== undefined) {
me.fireEvent('saveScene');
}
if (searchReplace(this, opt)) {
num++
}
if (num) {
me.fireEvent('saveScene');
}
}
return num;
},
notNeedUndo: 1
}
}
}
});
// plugins/customstyle.js
/**
* 自定义样式
* @file
* @since 1.2.6.1
*/
/**
* 根据config配置文件里“customstyle”选项的值对匹配的标签执行样式替换。
* @command customstyle
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand( 'customstyle' );
* ```
*/
UE.plugins['customstyle'] = function () {
var me = this;
me.setOpt({
'customstyle': [
{ tag: 'h1', name: 'tc', style: 'font-size:32px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;margin:0 0 20px 0;' },
{ tag: 'h1', name: 'tl', style: 'font-size:32px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:left;margin:0 0 10px 0;' },
{ tag: 'span', name: 'im', style: 'font-size:16px;font-style:italic;font-weight:bold;line-height:18px;' },
{ tag: 'span', name: 'hi', style: 'font-size:16px;font-style:italic;font-weight:bold;color:rgb(51, 153, 204);line-height:18px;' }
]
});
me.commands['customstyle'] = {
execCommand: function (cmdName, obj) {
var me = this,
tagName = obj.tag,
node = domUtils.findParent(me.selection.getStart(), function (node) {
return node.getAttribute('label');
}, true),
range, bk, tmpObj = {};
for (var p in obj) {
if (obj[p] !== undefined)
tmpObj[p] = obj[p];
}
delete tmpObj.tag;
if (node && node.getAttribute('label') == obj.label) {
range = this.selection.getRange();
bk = range.createBookmark();
if (range.collapsed) {
//trace:1732 删掉自定义标签,要有p来回填站位
if (dtd.$block[node.tagName]) {
var fillNode = me.document.createElement('p');
domUtils.moveChild(node, fillNode);
node.parentNode.insertBefore(fillNode, node);
domUtils.remove(node);
} else {
domUtils.remove(node, true);
}
} else {
var common = domUtils.getCommonAncestor(bk.start, bk.end),
nodes = domUtils.getElementsByTagName(common, tagName);
if (new RegExp(tagName, 'i').test(common.tagName)) {
nodes.push(common);
}
for (var i = 0, ni; ni = nodes[i++];) {
if (ni.getAttribute('label') == obj.label) {
var ps = domUtils.getPosition(ni, bk.start), pe = domUtils.getPosition(ni, bk.end);
if ((ps & domUtils.POSITION_FOLLOWING || ps & domUtils.POSITION_CONTAINS)
&&
(pe & domUtils.POSITION_PRECEDING || pe & domUtils.POSITION_CONTAINS)
)
if (dtd.$block[tagName]) {
var fillNode = me.document.createElement('p');
domUtils.moveChild(ni, fillNode);
ni.parentNode.insertBefore(fillNode, ni);
}
domUtils.remove(ni, true);
}
}
node = domUtils.findParent(common, function (node) {
return node.getAttribute('label') == obj.label;
}, true);
if (node) {
domUtils.remove(node, true);
}
}
range.moveToBookmark(bk).select();
} else {
if (dtd.$block[tagName]) {
this.execCommand('paragraph', tagName, tmpObj, 'customstyle');
range = me.selection.getRange();
if (!range.collapsed) {
range.collapse();
node = domUtils.findParent(me.selection.getStart(), function (node) {
return node.getAttribute('label') == obj.label;
}, true);
var pNode = me.document.createElement('p');
domUtils.insertAfter(node, pNode);
domUtils.fillNode(me.document, pNode);
range.setStart(pNode, 0).setCursor();
}
} else {
range = me.selection.getRange();
if (range.collapsed) {
node = me.document.createElement(tagName);
domUtils.setAttributes(node, tmpObj);
range.insertNode(node).setStart(node, 0).setCursor();
return;
}
bk = range.createBookmark();
range.applyInlineStyle(tagName, tmpObj).moveToBookmark(bk).select();
}
}
},
queryCommandValue: function () {
var parent = domUtils.filterNodeList(
this.selection.getStartElementPath(),
function (node) { return node.getAttribute('label') }
);
return parent ? parent.getAttribute('label') : '';
}
};
//当去掉customstyle是,如果是块元素,用p代替
me.addListener('keyup', function (type, evt) {
var keyCode = evt.keyCode || evt.which;
if (keyCode == 32 || keyCode == 13) {
var range = me.selection.getRange();
if (range.collapsed) {
var node = domUtils.findParent(me.selection.getStart(), function (node) {
return node.getAttribute('label');
}, true);
if (node && dtd.$block[node.tagName] && domUtils.isEmptyNode(node)) {
var p = me.document.createElement('p');
domUtils.insertAfter(node, p);
domUtils.fillNode(me.document, p);
domUtils.remove(node);
range.setStart(p, 0).setCursor();
}
}
}
});
};
// plugins/catchremoteimage.js
///import core
///commands 远程图片抓取
///commandsName catchRemoteImage,catchremoteimageenable
///commandsTitle 远程图片抓取
/**
* 远程图片抓取,当开启本插件时所有不符合本地域名的图片都将被抓取成为本地服务器上的图片
*/
UE.plugins['catchremoteimage'] = function () {
var me = this,
ajax = UE.ajax;
/* 设置默认值 */
if (me.options.catchRemoteImageEnable === false) return;
me.setOpt({
catchRemoteImageEnable: false
});
me.addListener("afterpaste", function () {
me.fireEvent("catchRemoteImage");
});
me.addListener("catchRemoteImage", function () {
var catcherLocalDomain = me.getOpt('catcherLocalDomain'),
catcherActionUrl = me.getActionUrl(me.getOpt('catcherActionName')),
catcherUrlPrefix = me.getOpt('catcherUrlPrefix'),
catcherFieldName = me.getOpt('catcherFieldName');
var remoteImages = [],
imgs = domUtils.getElementsByTagName(me.document, "img"),
test = function (src, urls) {
if (src.indexOf(location.host) != -1 || /(^\.)|(^\/)/.test(src)) {
return true;
}
if (urls) {
for (var j = 0, url; url = urls[j++];) {
if (src.indexOf(url) !== -1) {
return true;
}
}
}
return false;
};
for (var i = 0, ci; ci = imgs[i++];) {
if (ci.getAttribute("word_img")) {
continue;
}
var src = ci.getAttribute("_src") || ci.src || "";
if (/^(https?|ftp):/i.test(src) && !test(src, catcherLocalDomain)) {
remoteImages.push(src);
}
}
if (remoteImages.length) {
catchremoteimage(remoteImages, {
//成功抓取
success: function (r) {
try {
var info = r.state !== undefined ? r : eval("(" + r.responseText + ")");
} catch (e) {
return;
}
/* 获取源路径和新路径 */
var i, j, ci, cj, oldSrc, newSrc, list = info.list;
for (i = 0; ci = imgs[i++];) {
oldSrc = ci.getAttribute("_src") || ci.src || "";
for (j = 0; cj = list[j++];) {
if (oldSrc == cj.source && cj.state == "SUCCESS") { //抓取失败时不做替换处理
newSrc = catcherUrlPrefix + cj.url;
domUtils.setAttributes(ci, {
"src": newSrc,
"_src": newSrc
});
break;
}
}
}
me.fireEvent('catchremotesuccess')
},
//回调失败,本次请求超时
error: function () {
me.fireEvent("catchremoteerror");
}
});
}
function catchremoteimage(imgs, callbacks) {
var params = utils.serializeParam(me.queryCommandValue('serverparam')) || '',
url = utils.formatUrl(catcherActionUrl + (catcherActionUrl.indexOf('?') == -1 ? '?' : '&') + params),
isJsonp = utils.isCrossDomainUrl(url),
opt = {
'method': 'POST',
'dataType': isJsonp ? 'jsonp' : '',
'timeout': 60000, //单位:毫秒,回调请求超时设置。目标用户如果网速不是很快的话此处建议设置一个较大的数值
'onsuccess': callbacks["success"],
'onerror': callbacks["error"]
};
opt[catcherFieldName] = imgs;
ajax.request(url, opt);
}
});
};
// plugins/snapscreen.js
/**
* 截屏插件,为UEditor提供插入支持
* @file
* @since 1.4.2
*/
UE.plugin.register('snapscreen', function () {
var me = this;
var snapplugin;
function getLocation(url) {
var search,
a = document.createElement('a'),
params = utils.serializeParam(me.queryCommandValue('serverparam')) || '';
a.href = url;
if (browser.ie) {
a.href = a.href;
}
search = a.search;
if (params) {
search = search + (search.indexOf('?') == -1 ? '?' : '&') + params;
search = search.replace(/[&]+/ig, '&');
}
return {
'port': a.port,
'hostname': a.hostname,
'path': a.pathname + search || + a.hash
}
}
return {
commands: {
/**
* 字体背景颜色
* @command snapscreen
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand('snapscreen');
* ```
*/
'snapscreen': {
execCommand: function (cmd) {
var url, local, res;
var lang = me.getLang("snapScreen_plugin");
if (!snapplugin) {
var container = me.container;
var doc = me.container.ownerDocument || me.container.document;
snapplugin = doc.createElement("object");
try { snapplugin.type = "application/x-pluginbaidusnap"; } catch (e) {
return;
}
snapplugin.style.cssText = "position:absolute;left:-9999px;width:0;height:0;";
snapplugin.setAttribute("width", "0");
snapplugin.setAttribute("height", "0");
container.appendChild(snapplugin);
}
function onSuccess(rs) {
try {
rs = eval("(" + rs + ")");
if (rs.state == 'SUCCESS') {
var opt = me.options;
me.execCommand('insertimage', {
src: opt.snapscreenUrlPrefix + rs.url,
_src: opt.snapscreenUrlPrefix + rs.url,
alt: rs.title || '',
floatStyle: opt.snapscreenImgAlign
});
} else {
alert(rs.state);
}
} catch (e) {
alert(lang.callBackErrorMsg);
}
}
url = me.getActionUrl(me.getOpt('snapscreenActionName'));
local = getLocation(url);
setTimeout(function () {
try {
res = snapplugin.saveSnapshot(local.hostname, local.path, local.port);
} catch (e) {
me.ui._dialogs['snapscreenDialog'].open();
return;
}
onSuccess(res);
}, 50);
},
queryCommandState: function () {
return (navigator.userAgent.indexOf("Windows", 0) != -1) ? 0 : -1;
}
}
}
}
});
// plugins/insertparagraph.js
/**
* 插入段落
* @file
* @since 1.2.6.1
*/
/**
* 插入段落
* @command insertparagraph
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* //editor是编辑器实例
* editor.execCommand( 'insertparagraph' );
* ```
*/
UE.commands['insertparagraph'] = {
execCommand: function (cmdName, front) {
var me = this,
range = me.selection.getRange(),
start = range.startContainer, tmpNode;
while (start) {
if (domUtils.isBody(start)) {
break;
}
tmpNode = start;
start = start.parentNode;
}
if (tmpNode) {
var p = me.document.createElement('p');
if (front) {
tmpNode.parentNode.insertBefore(p, tmpNode)
} else {
tmpNode.parentNode.insertBefore(p, tmpNode.nextSibling)
}
domUtils.fillNode(me.document, p);
range.setStart(p, 0).setCursor(false, true);
}
}
};
// plugins/webapp.js
/**
* 百度应用
* @file
* @since 1.2.6.1
*/
/**
* 插入百度应用
* @command webapp
* @method execCommand
* @remind 需要百度APPKey
* @remind 百度应用主页: http://app.baidu.com/
* @param { Object } appOptions 应用所需的参数项, 支持的key有: title=>应用标题, width=>应用容器宽度,
* height=>应用容器高度,logo=>应用logo,url=>应用地址
* @example
* ```javascript
* //editor是编辑器实例
* //在编辑器里插入一个“植物大战僵尸”的APP
* editor.execCommand( 'webapp' , {
* title: '植物大战僵尸',
* width: 560,
* height: 465,
* logo: '应用展示的图片',
* url: '百度应用的地址'
* } );
* ```
*/
//UE.plugins['webapp'] = function () {
// var me = this;
// function createInsertStr( obj, toIframe, addParagraph ) {
// return !toIframe ?
// (addParagraph ? '' : '') + ' ' +
// (addParagraph ? '
' : '')
// :
// '';
// }
//
// function switchImgAndIframe( img2frame ) {
// var tmpdiv,
// nodes = domUtils.getElementsByTagName( me.document, !img2frame ? "iframe" : "img" );
// for ( var i = 0, node; node = nodes[i++]; ) {
// if ( node.className != "edui-faked-webapp" ){
// continue;
// }
// tmpdiv = me.document.createElement( "div" );
// tmpdiv.innerHTML = createInsertStr( img2frame ? {url:node.getAttribute( "_url" ), width:node.width, height:node.height,title:node.title,logo:node.style.backgroundImage.replace("url(","").replace(")","")} : {url:node.getAttribute( "src", 2 ),title:node.title, width:node.width, height:node.height,logo:node.getAttribute("logo_url")}, img2frame ? true : false,false );
// node.parentNode.replaceChild( tmpdiv.firstChild, node );
// }
// }
//
// me.addListener( "beforegetcontent", function () {
// switchImgAndIframe( true );
// } );
// me.addListener( 'aftersetcontent', function () {
// switchImgAndIframe( false );
// } );
// me.addListener( 'aftergetcontent', function ( cmdName ) {
// if ( cmdName == 'aftergetcontent' && me.queryCommandState( 'source' ) ){
// return;
// }
// switchImgAndIframe( false );
// } );
//
// me.commands['webapp'] = {
// execCommand:function ( cmd, obj ) {
// me.execCommand( "inserthtml", createInsertStr( obj, false,true ) );
// }
// };
//};
UE.plugin.register('webapp', function () {
var me = this;
function createInsertStr(obj, toEmbed) {
return !toEmbed ?
' '
:
''
}
return {
outputRule: function (root) {
utils.each(root.getNodesByTagName('img'), function (node) {
var html;
if (node.getAttr('class') == 'edui-faked-webapp') {
html = createInsertStr({
title: node.getAttr('title'),
'width': node.getAttr('width'),
'height': node.getAttr('height'),
'align': node.getAttr('align'),
'cssfloat': node.getStyle('float'),
'url': node.getAttr("_url"),
'logo': node.getAttr('_logo_url')
}, true);
var embed = UE.uNode.createElement(html);
node.parentNode.replaceChild(embed, node);
}
})
},
inputRule: function (root) {
utils.each(root.getNodesByTagName('iframe'), function (node) {
if (node.getAttr('class') == 'edui-faked-webapp') {
var img = UE.uNode.createElement(createInsertStr({
title: node.getAttr('title'),
'width': node.getAttr('width'),
'height': node.getAttr('height'),
'align': node.getAttr('align'),
'cssfloat': node.getStyle('float'),
'url': node.getAttr("src"),
'logo': node.getAttr('logo_url')
}));
node.parentNode.replaceChild(img, node);
}
})
},
commands: {
/**
* 插入百度应用
* @command webapp
* @method execCommand
* @remind 需要百度APPKey
* @remind 百度应用主页: http://app.baidu.com/
* @param { Object } appOptions 应用所需的参数项, 支持的key有: title=>应用标题, width=>应用容器宽度,
* height=>应用容器高度,logo=>应用logo,url=>应用地址
* @example
* ```javascript
* //editor是编辑器实例
* //在编辑器里插入一个“植物大战僵尸”的APP
* editor.execCommand( 'webapp' , {
* title: '植物大战僵尸',
* width: 560,
* height: 465,
* logo: '应用展示的图片',
* url: '百度应用的地址'
* } );
* ```
*/
'webapp': {
execCommand: function (cmd, obj) {
var me = this,
str = createInsertStr(utils.extend(obj, {
align: 'none'
}), false);
me.execCommand("inserthtml", str);
},
queryCommandState: function () {
var me = this,
img = me.selection.getRange().getClosedNode(),
flag = img && (img.className == "edui-faked-webapp");
return flag ? 1 : 0;
}
}
}
}
});
// plugins/template.js
///import core
///import plugins\inserthtml.js
///import plugins\cleardoc.js
///commands 模板
///commandsName template
///commandsTitle 模板
///commandsDialog dialogs\template
UE.plugins['template'] = function () {
UE.commands['template'] = {
execCommand: function (cmd, obj) {
obj.html && this.execCommand("inserthtml", obj.html);
}
};
this.addListener("click", function (type, evt) {
var el = evt.target || evt.srcElement,
range = this.selection.getRange();
var tnode = domUtils.findParent(el, function (node) {
if (node.className && domUtils.hasClass(node, "ue_t")) {
return node;
}
}, true);
tnode && range.selectNode(tnode).shrinkBoundary().select();
});
this.addListener("keydown", function (type, evt) {
var range = this.selection.getRange();
if (!range.collapsed) {
if (!evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
var tnode = domUtils.findParent(range.startContainer, function (node) {
if (node.className && domUtils.hasClass(node, "ue_t")) {
return node;
}
}, true);
if (tnode) {
domUtils.removeClasses(tnode, ["ue_t"]);
}
}
}
});
};
// plugins/music.js
/**
* 插入音乐命令
* @file
*/
UE.plugin.register('music', function () {
var me = this;
function creatInsertStr(url, width, height, align, cssfloat, toEmbed) {
return !toEmbed ?
' '
:
'';
}
return {
outputRule: function (root) {
utils.each(root.getNodesByTagName('img'), function (node) {
var html;
if (node.getAttr('class') == 'edui-faked-music') {
var cssfloat = node.getStyle('float');
var align = node.getAttr('align');
html = creatInsertStr(node.getAttr("_url"), node.getAttr('width'), node.getAttr('height'), align, cssfloat, true);
var embed = UE.uNode.createElement(html);
node.parentNode.replaceChild(embed, node);
}
})
},
inputRule: function (root) {
utils.each(root.getNodesByTagName('embed'), function (node) {
if (node.getAttr('class') == 'edui-faked-music') {
var cssfloat = node.getStyle('float');
var align = node.getAttr('align');
html = creatInsertStr(node.getAttr("src"), node.getAttr('width'), node.getAttr('height'), align, cssfloat, false);
var img = UE.uNode.createElement(html);
node.parentNode.replaceChild(img, node);
}
})
},
commands: {
/**
* 插入音乐
* @command music
* @method execCommand
* @param { Object } musicOptions 插入音乐的参数项, 支持的key有: url=>音乐地址;
* width=>音乐容器宽度;height=>音乐容器高度;align=>音乐文件的对齐方式, 可选值有: left, center, right, none
* @example
* ```javascript
* //editor是编辑器实例
* //在编辑器里插入一个“植物大战僵尸”的APP
* editor.execCommand( 'music' , {
* width: 400,
* height: 95,
* align: "center",
* url: "音乐地址"
* } );
* ```
*/
'music': {
execCommand: function (cmd, musicObj) {
var me = this,
str = creatInsertStr(musicObj.url, musicObj.width || 400, musicObj.height || 95, "none", false);
me.execCommand("inserthtml", str);
},
queryCommandState: function () {
var me = this,
img = me.selection.getRange().getClosedNode(),
flag = img && (img.className == "edui-faked-music");
return flag ? 1 : 0;
}
}
}
}
});
// plugins/autoupload.js
/**
* @description
* 1.拖放文件到编辑区域,自动上传并插入到选区
* 2.插入粘贴板的图片,自动上传并插入到选区
* @author Jinqn
* @date 2013-10-14
*/
UE.plugin.register('autoupload', function () {
function sendAndInsertFile(file, editor) {
var me = editor;
//模拟数据
var fieldName, urlPrefix, maxSize, allowFiles, actionUrl,
loadingHtml, errorHandler, successHandler,
filetype = /image\/\w+/i.test(file.type) ? 'image' : 'file',
loadingId = 'loading_' + (+new Date()).toString(36);
fieldName = me.getOpt(filetype + 'FieldName');
urlPrefix = me.getOpt(filetype + 'UrlPrefix');
maxSize = me.getOpt(filetype + 'MaxSize');
allowFiles = me.getOpt(filetype + 'AllowFiles');
actionUrl = me.getActionUrl(me.getOpt(filetype + 'ActionName'));
errorHandler = function (title) {
var loader = me.document.getElementById(loadingId);
loader && domUtils.remove(loader);
me.fireEvent('showmessage', {
'id': loadingId,
'content': title,
'type': 'error',
'timeout': 4000
});
};
if (filetype == 'image') {
loadingHtml = ' ';
successHandler = function (data) {
var link = urlPrefix + data.url,
loader = me.document.getElementById(loadingId);
if (loader) {
loader.setAttribute('src', link);
loader.setAttribute('_src', link);
loader.setAttribute('title', data.title || '');
loader.setAttribute('alt', data.original || '');
loader.removeAttribute('id');
domUtils.removeClasses(loader, 'loadingclass');
}
};
} else {
loadingHtml = '' +
' ' +
'
';
successHandler = function (data) {
var link = urlPrefix + data.url,
loader = me.document.getElementById(loadingId);
var rng = me.selection.getRange(),
bk = rng.createBookmark();
rng.selectNode(loader).select();
me.execCommand('insertfile', { 'url': link });
rng.moveToBookmark(bk).select();
};
}
/* 插入loading的占位符 */
me.execCommand('inserthtml', loadingHtml);
/* 判断后端配置是否没有加载成功 */
if (!me.getOpt(filetype + 'ActionName')) {
errorHandler(me.getLang('autoupload.errorLoadConfig'));
return;
}
/* 判断文件大小是否超出限制 */
if (file.size > maxSize) {
errorHandler(me.getLang('autoupload.exceedSizeError'));
return;
}
/* 判断文件格式是否超出允许 */
var fileext = file.name ? file.name.substr(file.name.lastIndexOf('.')) : '';
if ((fileext && filetype != 'image') || (allowFiles && (allowFiles.join('') + '.').indexOf(fileext.toLowerCase() + '.') == -1)) {
errorHandler(me.getLang('autoupload.exceedTypeError'));
return;
}
/* 创建Ajax并提交 */
var xhr = new XMLHttpRequest(),
fd = new FormData(),
params = utils.serializeParam(me.queryCommandValue('serverparam')) || '',
url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?' : '&') + params);
fd.append(fieldName, file, file.name || ('blob.' + file.type.substr('image/'.length)));
fd.append('type', 'ajax');
xhr.open("post", url, true);
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.addEventListener('load', function (e) {
try {
var json = (new Function("return " + utils.trim(e.target.response)))();
if (json.state == 'SUCCESS' && json.url) {
successHandler(json);
} else {
errorHandler(json.state);
}
} catch (er) {
errorHandler(me.getLang('autoupload.loadError'));
}
});
xhr.send(fd);
}
function getPasteImage(e) {
return e.clipboardData && e.clipboardData.items && e.clipboardData.items.length == 1 && /^image\//.test(e.clipboardData.items[0].type) ? e.clipboardData.items : null;
}
function getDropImage(e) {
return e.dataTransfer && e.dataTransfer.files ? e.dataTransfer.files : null;
}
return {
outputRule: function (root) {
utils.each(root.getNodesByTagName('img'), function (n) {
if (/\b(loaderrorclass)|(bloaderrorclass)\b/.test(n.getAttr('class'))) {
n.parentNode.removeChild(n);
}
});
utils.each(root.getNodesByTagName('p'), function (n) {
if (/\bloadpara\b/.test(n.getAttr('class'))) {
n.parentNode.removeChild(n);
}
});
},
bindEvents: {
//插入粘贴板的图片,拖放插入图片
'ready': function (e) {
var me = this;
if (window.FormData && window.FileReader) {
domUtils.on(me.body, 'paste drop', function (e) {
var hasImg = false,
items;
//获取粘贴板文件列表或者拖放文件列表
items = e.type == 'paste' ? getPasteImage(e) : getDropImage(e);
if (items) {
var len = items.length,
file;
while (len--) {
file = items[len];
if (file.getAsFile) file = file.getAsFile();
if (file && file.size > 0) {
sendAndInsertFile(file, me);
hasImg = true;
}
}
hasImg && e.preventDefault();
}
});
//取消拖放图片时出现的文字光标位置提示
domUtils.on(me.body, 'dragover', function (e) {
if (e.dataTransfer.types[0] == 'Files') {
e.preventDefault();
}
});
//设置loading的样式
utils.cssRule('loading',
'.loadingclass{display:inline-block;cursor:default;background: url(\''
+ this.options.themePath
+ this.options.theme + '/images/loading.gif\') no-repeat center center transparent;border:1px solid #cccccc;margin-left:1px;height: 22px;width: 22px;}\n' +
'.loaderrorclass{display:inline-block;cursor:default;background: url(\''
+ this.options.themePath
+ this.options.theme + '/images/loaderror.png\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;' +
'}',
this.document);
}
}
}
}
});
// plugins/autosave.js
UE.plugin.register('autosave', function () {
var me = this,
//无限循环保护
lastSaveTime = new Date(),
//最小保存间隔时间
MIN_TIME = 20,
//auto save key
saveKey = null;
function save(editor) {
var saveData;
if (new Date() - lastSaveTime < MIN_TIME) {
return;
}
if (!editor.hasContents()) {
//这里不能调用命令来删除, 会造成事件死循环
saveKey && me.removePreferences(saveKey);
return;
}
lastSaveTime = new Date();
editor._saveFlag = null;
saveData = me.body.innerHTML;
if (editor.fireEvent("beforeautosave", {
content: saveData
}) === false) {
return;
}
me.setPreferences(saveKey, saveData);
editor.fireEvent("afterautosave", {
content: saveData
});
}
return {
defaultOptions: {
//默认间隔时间
saveInterval: 500
},
bindEvents: {
'ready': function () {
var _suffix = "-drafts-data",
key = null;
if (me.key) {
key = me.key + _suffix;
} else {
key = (me.container.parentNode.id || 'ue-common') + _suffix;
}
//页面地址+编辑器ID 保持唯一
saveKey = (location.protocol + location.host + location.pathname).replace(/[.:\/]/g, '_') + key;
},
'contentchange': function () {
if (!saveKey) {
return;
}
if (me._saveFlag) {
window.clearTimeout(me._saveFlag);
}
if (me.options.saveInterval > 0) {
me._saveFlag = window.setTimeout(function () {
save(me);
}, me.options.saveInterval);
} else {
save(me);
}
}
},
commands: {
'clearlocaldata': {
execCommand: function (cmd, name) {
if (saveKey && me.getPreferences(saveKey)) {
me.removePreferences(saveKey)
}
},
notNeedUndo: true,
ignoreContentChange: true
},
'getlocaldata': {
execCommand: function (cmd, name) {
return saveKey ? me.getPreferences(saveKey) || '' : '';
},
notNeedUndo: true,
ignoreContentChange: true
},
'drafts': {
execCommand: function (cmd, name) {
if (saveKey) {
me.body.innerHTML = me.getPreferences(saveKey) || '' + domUtils.fillHtml + '
';
me.focus(true);
}
},
queryCommandState: function () {
return saveKey ? (me.getPreferences(saveKey) === null ? -1 : 0) : -1;
},
notNeedUndo: true,
ignoreContentChange: true
}
}
}
});
// plugins/charts.js
UE.plugin.register('charts', function () {
var me = this;
return {
bindEvents: {
'chartserror': function () {
}
},
commands: {
'charts': {
execCommand: function (cmd, data) {
var tableNode = domUtils.findParentByTagName(this.selection.getRange().startContainer, 'table', true),
flagText = [],
config = {};
if (!tableNode) {
return false;
}
if (!validData(tableNode)) {
me.fireEvent("chartserror");
return false;
}
config.title = data.title || '';
config.subTitle = data.subTitle || '';
config.xTitle = data.xTitle || '';
config.yTitle = data.yTitle || '';
config.suffix = data.suffix || '';
config.tip = data.tip || '';
//数据对齐方式
config.dataFormat = data.tableDataFormat || '';
//图表类型
config.chartType = data.chartType || 0;
for (var key in config) {
if (!config.hasOwnProperty(key)) {
continue;
}
flagText.push(key + ":" + config[key]);
}
tableNode.setAttribute("data-chart", flagText.join(";"));
domUtils.addClass(tableNode, "edui-charts-table");
},
queryCommandState: function (cmd, name) {
var tableNode = domUtils.findParentByTagName(this.selection.getRange().startContainer, 'table', true);
return tableNode && validData(tableNode) ? 0 : -1;
}
}
},
inputRule: function (root) {
utils.each(root.getNodesByTagName('table'), function (tableNode) {
if (tableNode.getAttr("data-chart") !== undefined) {
tableNode.setAttr("style");
}
})
},
outputRule: function (root) {
utils.each(root.getNodesByTagName('table'), function (tableNode) {
if (tableNode.getAttr("data-chart") !== undefined) {
tableNode.setAttr("style", "display: none;");
}
})
}
}
function validData(table) {
var firstRows = null,
cellCount = 0;
//行数不够
if (table.rows.length < 2) {
return false;
}
//列数不够
if (table.rows[0].cells.length < 2) {
return false;
}
//第一行所有cell必须是th
firstRows = table.rows[0].cells;
cellCount = firstRows.length;
for (var i = 0, cell; cell = firstRows[i]; i++) {
if (cell.tagName.toLowerCase() !== 'th') {
return false;
}
}
for (var i = 1, row; row = table.rows[i]; i++) {
//每行单元格数不匹配, 返回false
if (row.cells.length != cellCount) {
return false;
}
//第一列不是th也返回false
if (row.cells[0].tagName.toLowerCase() !== 'th') {
return false;
}
for (var j = 1, cell; cell = row.cells[j]; j++) {
var value = utils.trim((cell.innerText || cell.textContent || ''));
value = value.replace(new RegExp(UE.dom.domUtils.fillChar, 'g'), '').replace(/^\s+|\s+$/g, '');
//必须是数字
if (!/^\d*\.?\d+$/.test(value)) {
return false;
}
}
}
return true;
}
});
// plugins/section.js
/**
* 目录大纲支持插件
* @file
* @since 1.3.0
*/
UE.plugin.register('section', function () {
/* 目录节点对象 */
function Section(option) {
this.tag = '';
this.level = -1,
this.dom = null;
this.nextSection = null;
this.previousSection = null;
this.parentSection = null;
this.startAddress = [];
this.endAddress = [];
this.children = [];
}
function getSection(option) {
var section = new Section();
return utils.extend(section, option);
}
function getNodeFromAddress(startAddress, root) {
var current = root;
for (var i = 0; i < startAddress.length; i++) {
if (!current.childNodes) return null;
current = current.childNodes[startAddress[i]];
}
return current;
}
var me = this;
return {
bindMultiEvents: {
type: 'aftersetcontent afterscencerestore',
handler: function () {
me.fireEvent('updateSections');
}
},
bindEvents: {
/* 初始化、拖拽、粘贴、执行setcontent之后 */
'ready': function () {
me.fireEvent('updateSections');
domUtils.on(me.body, 'drop paste', function () {
me.fireEvent('updateSections');
});
},
/* 执行paragraph命令之后 */
'afterexeccommand': function (type, cmd) {
if (cmd == 'paragraph') {
me.fireEvent('updateSections');
}
},
/* 部分键盘操作,触发updateSections事件 */
'keyup': function (type, e) {
var me = this,
range = me.selection.getRange();
if (range.collapsed != true) {
me.fireEvent('updateSections');
} else {
var keyCode = e.keyCode || e.which;
if (keyCode == 13 || keyCode == 8 || keyCode == 46) {
me.fireEvent('updateSections');
}
}
}
},
commands: {
'getsections': {
execCommand: function (cmd, levels) {
var levelFn = levels || ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
for (var i = 0; i < levelFn.length; i++) {
if (typeof levelFn[i] == 'string') {
levelFn[i] = function (fn) {
return function (node) {
return node.tagName == fn.toUpperCase()
};
}(levelFn[i]);
} else if (typeof levelFn[i] != 'function') {
levelFn[i] = function (node) {
return null;
}
}
}
function getSectionLevel(node) {
for (var i = 0; i < levelFn.length; i++) {
if (levelFn[i](node)) return i;
}
return -1;
}
var me = this,
Directory = getSection({ 'level': -1, 'title': 'root' }),
previous = Directory;
function traversal(node, Directory) {
var level,
tmpSection = null,
parent,
child,
children = node.childNodes;
for (var i = 0, len = children.length; i < len; i++) {
child = children[i];
level = getSectionLevel(child);
if (level >= 0) {
var address = me.selection.getRange().selectNode(child).createAddress(true).startAddress,
current = getSection({
'tag': child.tagName,
'title': child.innerText || child.textContent || '',
'level': level,
'dom': child,
'startAddress': utils.clone(address, []),
'endAddress': utils.clone(address, []),
'children': []
});
previous.nextSection = current;
current.previousSection = previous;
parent = previous;
while (level <= parent.level) {
parent = parent.parentSection;
}
current.parentSection = parent;
parent.children.push(current);
tmpSection = previous = current;
} else {
child.nodeType === 1 && traversal(child, Directory);
tmpSection && tmpSection.endAddress[tmpSection.endAddress.length - 1]++;
}
}
}
traversal(me.body, Directory);
return Directory;
},
notNeedUndo: true
},
'movesection': {
execCommand: function (cmd, sourceSection, targetSection, isAfter) {
var me = this,
targetAddress,
target;
if (!sourceSection || !targetSection || targetSection.level == -1) return;
targetAddress = isAfter ? targetSection.endAddress : targetSection.startAddress;
target = getNodeFromAddress(targetAddress, me.body);
/* 判断目标地址是否被源章节包含 */
if (!targetAddress || !target || isContainsAddress(sourceSection.startAddress, sourceSection.endAddress, targetAddress)) return;
var startNode = getNodeFromAddress(sourceSection.startAddress, me.body),
endNode = getNodeFromAddress(sourceSection.endAddress, me.body),
current,
nextNode;
if (isAfter) {
current = endNode;
while (current && !(domUtils.getPosition(startNode, current) & domUtils.POSITION_FOLLOWING)) {
nextNode = current.previousSibling;
domUtils.insertAfter(target, current);
if (current == startNode) break;
current = nextNode;
}
} else {
current = startNode;
while (current && !(domUtils.getPosition(current, endNode) & domUtils.POSITION_FOLLOWING)) {
nextNode = current.nextSibling;
target.parentNode.insertBefore(current, target);
if (current == endNode) break;
current = nextNode;
}
}
me.fireEvent('updateSections');
/* 获取地址的包含关系 */
function isContainsAddress(startAddress, endAddress, addressTarget) {
var isAfterStartAddress = false,
isBeforeEndAddress = false;
for (var i = 0; i < startAddress.length; i++) {
if (i >= addressTarget.length) break;
if (addressTarget[i] > startAddress[i]) {
isAfterStartAddress = true;
break;
} else if (addressTarget[i] < startAddress[i]) {
break;
}
}
for (var i = 0; i < endAddress.length; i++) {
if (i >= addressTarget.length) break;
if (addressTarget[i] < startAddress[i]) {
isBeforeEndAddress = true;
break;
} else if (addressTarget[i] > startAddress[i]) {
break;
}
}
return isAfterStartAddress && isBeforeEndAddress;
}
}
},
'deletesection': {
execCommand: function (cmd, section, keepChildren) {
var me = this;
if (!section) return;
function getNodeFromAddress(startAddress) {
var current = me.body;
for (var i = 0; i < startAddress.length; i++) {
if (!current.childNodes) return null;
current = current.childNodes[startAddress[i]];
}
return current;
}
var startNode = getNodeFromAddress(section.startAddress),
endNode = getNodeFromAddress(section.endAddress),
current = startNode,
nextNode;
if (!keepChildren) {
while (current && domUtils.inDoc(endNode, me.document) && !(domUtils.getPosition(current, endNode) & domUtils.POSITION_FOLLOWING)) {
nextNode = current.nextSibling;
domUtils.remove(current);
current = nextNode;
}
} else {
domUtils.remove(current);
}
me.fireEvent('updateSections');
}
},
'selectsection': {
execCommand: function (cmd, section) {
if (!section && !section.dom) return false;
var me = this,
range = me.selection.getRange(),
address = {
'startAddress': utils.clone(section.startAddress, []),
'endAddress': utils.clone(section.endAddress, [])
};
address.endAddress[address.endAddress.length - 1]++;
range.moveToAddress(address).select().scrollToView();
return true;
},
notNeedUndo: true
},
'scrolltosection': {
execCommand: function (cmd, section) {
if (!section && !section.dom) return false;
var me = this,
range = me.selection.getRange(),
address = {
'startAddress': section.startAddress,
'endAddress': section.endAddress
};
address.endAddress[address.endAddress.length - 1]++;
range.moveToAddress(address).scrollToView();
return true;
},
notNeedUndo: true
}
}
}
});
// plugins/simpleupload.js
/**
* @description
* 简单上传:点击按钮,直接选择文件上传
* @author Jinqn
* @date 2014-03-31
*/
UE.plugin.register('simpleupload', function () {
var me = this,
isLoaded = false,
containerBtn;
function initUploadBtn() {
var w = containerBtn.offsetWidth || 20,
h = containerBtn.offsetHeight || 20,
btnIframe = document.createElement('iframe'),
btnStyle = 'display:block;width:' + w + 'px;height:' + h + 'px;overflow:hidden;border:0;margin:0;padding:0;position:absolute;top:0;left:0;filter:alpha(opacity=0);-moz-opacity:0;-khtml-opacity: 0;opacity: 0;cursor:pointer;';
domUtils.on(btnIframe, 'load', function () {
var timestrap = (+new Date()).toString(36),
wrapper,
btnIframeDoc,
btnIframeBody;
btnIframeDoc = (btnIframe.contentDocument || btnIframe.contentWindow.document);
btnIframeBody = btnIframeDoc.body;
wrapper = btnIframeDoc.createElement('div');
wrapper.innerHTML = '' +
'';
wrapper.className = 'edui-' + me.options.theme;
wrapper.id = me.ui.id + '_iframeupload';
btnIframeBody.style.cssText = btnStyle;
btnIframeBody.style.width = w + 'px';
btnIframeBody.style.height = h + 'px';
btnIframeBody.appendChild(wrapper);
if (btnIframeBody.parentNode) {
btnIframeBody.parentNode.style.width = w + 'px';
btnIframeBody.parentNode.style.height = w + 'px';
}
var form = btnIframeDoc.getElementById('edui_form_' + timestrap);
var input = btnIframeDoc.getElementById('edui_input_' + timestrap);
var iframe = btnIframeDoc.getElementById('edui_iframe_' + timestrap);
domUtils.on(input, 'change', function () {
if (!input.value) return;
var loadingId = 'loading_' + (+new Date()).toString(36);
var params = utils.serializeParam(me.queryCommandValue('serverparam')) || '';
var imageActionUrl = me.getActionUrl(me.getOpt('imageActionName'));
var allowFiles = me.getOpt('imageAllowFiles');
me.focus();
me.execCommand('inserthtml', ' ');
function callback() {
try {
var link, json, loader,
body = (iframe.contentDocument || iframe.contentWindow.document).body,
result = body.innerText || body.textContent || '';
json = (new Function("return " + result))();
link = me.options.imageUrlPrefix + json.url;
if (json.state == 'SUCCESS' && json.url) {
loader = me.document.getElementById(loadingId);
loader.setAttribute('src', link);
loader.setAttribute('_src', link);
loader.setAttribute('title', json.title || '');
loader.setAttribute('alt', json.original || '');
loader.removeAttribute('id');
domUtils.removeClasses(loader, 'loadingclass');
} else {
showErrorLoader && showErrorLoader(json.state);
}
} catch (er) {
showErrorLoader && showErrorLoader(me.getLang('simpleupload.loadError'));
}
form.reset();
domUtils.un(iframe, 'load', callback);
}
function showErrorLoader(title) {
if (loadingId) {
var loader = me.document.getElementById(loadingId);
loader && domUtils.remove(loader);
me.fireEvent('showmessage', {
'id': loadingId,
'content': title,
'type': 'error',
'timeout': 4000
});
}
}
/* 判断后端配置是否没有加载成功 */
if (!me.getOpt('imageActionName')) {
errorHandler(me.getLang('autoupload.errorLoadConfig'));
return;
}
// 判断文件格式是否错误
var filename = input.value,
fileext = filename ? filename.substr(filename.lastIndexOf('.')) : '';
if (!fileext || (allowFiles && (allowFiles.join('') + '.').indexOf(fileext.toLowerCase() + '.') == -1)) {
showErrorLoader(me.getLang('simpleupload.exceedTypeError'));
return;
}
domUtils.on(iframe, 'load', callback);
form.action = utils.formatUrl(imageActionUrl + (imageActionUrl.indexOf('?') == -1 ? '?' : '&') + params);
form.submit();
});
var stateTimer;
me.addListener('selectionchange', function () {
clearTimeout(stateTimer);
stateTimer = setTimeout(function () {
var state = me.queryCommandState('simpleupload');
if (state == -1) {
input.disabled = 'disabled';
} else {
input.disabled = false;
}
}, 400);
});
isLoaded = true;
});
btnIframe.style.cssText = btnStyle;
containerBtn.appendChild(btnIframe);
}
return {
bindEvents: {
'ready': function () {
//设置loading的样式
utils.cssRule('loading',
'.loadingclass{display:inline-block;cursor:default;background: url(\''
+ this.options.themePath
+ this.options.theme + '/images/loading.gif\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;}\n' +
'.loaderrorclass{display:inline-block;cursor:default;background: url(\''
+ this.options.themePath
+ this.options.theme + '/images/loaderror.png\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;' +
'}',
this.document);
},
/* 初始化简单上传按钮 */
'simpleuploadbtnready': function (type, container) {
containerBtn = container;
me.afterConfigReady(initUploadBtn);
}
},
outputRule: function (root) {
utils.each(root.getNodesByTagName('img'), function (n) {
if (/\b(loaderrorclass)|(bloaderrorclass)\b/.test(n.getAttr('class'))) {
n.parentNode.removeChild(n);
}
});
},
commands: {
'simpleupload': {
queryCommandState: function () {
return isLoaded ? 0 : -1;
}
}
}
}
});
// plugins/serverparam.js
/**
* 服务器提交的额外参数列表设置插件
* @file
* @since 1.2.6.1
*/
UE.plugin.register('serverparam', function () {
var me = this,
serverParam = {};
return {
commands: {
/**
* 修改服务器提交的额外参数列表,清除所有项
* @command serverparam
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.execCommand('serverparam');
* editor.queryCommandValue('serverparam'); //返回空
* ```
*/
/**
* 修改服务器提交的额外参数列表,删除指定项
* @command serverparam
* @method execCommand
* @param { String } cmd 命令字符串
* @param { String } key 要清除的属性
* @example
* ```javascript
* editor.execCommand('serverparam', 'name'); //删除属性name
* ```
*/
/**
* 修改服务器提交的额外参数列表,使用键值添加项
* @command serverparam
* @method execCommand
* @param { String } cmd 命令字符串
* @param { String } key 要添加的属性
* @param { String } value 要添加属性的值
* @example
* ```javascript
* editor.execCommand('serverparam', 'name', 'hello');
* editor.queryCommandValue('serverparam'); //返回对象 {'name': 'hello'}
* ```
*/
/**
* 修改服务器提交的额外参数列表,传入键值对对象添加多项
* @command serverparam
* @method execCommand
* @param { String } cmd 命令字符串
* @param { Object } key 传入的键值对对象
* @example
* ```javascript
* editor.execCommand('serverparam', {'name': 'hello'});
* editor.queryCommandValue('serverparam'); //返回对象 {'name': 'hello'}
* ```
*/
/**
* 修改服务器提交的额外参数列表,使用自定义函数添加多项
* @command serverparam
* @method execCommand
* @param { String } cmd 命令字符串
* @param { Function } key 自定义获取参数的函数
* @example
* ```javascript
* editor.execCommand('serverparam', function(editor){
* return {'key': 'value'};
* });
* editor.queryCommandValue('serverparam'); //返回对象 {'key': 'value'}
* ```
*/
/**
* 获取服务器提交的额外参数列表
* @command serverparam
* @method queryCommandValue
* @param { String } cmd 命令字符串
* @example
* ```javascript
* editor.queryCommandValue( 'serverparam' ); //返回对象 {'key': 'value'}
* ```
*/
'serverparam': {
execCommand: function (cmd, key, value) {
if (key === undefined || key === null) { //不传参数,清空列表
serverParam = {};
} else if (utils.isString(key)) { //传入键值
if (value === undefined || value === null) {
delete serverParam[key];
} else {
serverParam[key] = value;
}
} else if (utils.isObject(key)) { //传入对象,覆盖列表项
utils.extend(serverParam, key, true);
} else if (utils.isFunction(key)) { //传入函数,添加列表项
utils.extend(serverParam, key(), true);
}
},
queryCommandValue: function () {
return serverParam || {};
}
}
}
}
});
// plugins/insertfile.js
/**
* 插入附件
*/
UE.plugin.register('insertfile', function () {
var me = this;
function getFileIcon(url) {
var ext = url.substr(url.lastIndexOf('.') + 1).toLowerCase(),
maps = {
"rar": "icon_rar.gif",
"zip": "icon_rar.gif",
"tar": "icon_rar.gif",
"gz": "icon_rar.gif",
"bz2": "icon_rar.gif",
"doc": "icon_doc.gif",
"docx": "icon_doc.gif",
"pdf": "icon_pdf.gif",
"mp3": "icon_mp3.gif",
"xls": "icon_xls.gif",
"chm": "icon_chm.gif",
"ppt": "icon_ppt.gif",
"pptx": "icon_ppt.gif",
"avi": "icon_mv.gif",
"rmvb": "icon_mv.gif",
"wmv": "icon_mv.gif",
"flv": "icon_mv.gif",
"swf": "icon_mv.gif",
"rm": "icon_mv.gif",
"exe": "icon_exe.gif",
"psd": "icon_psd.gif",
"txt": "icon_txt.gif",
"jpg": "icon_jpg.gif",
"png": "icon_jpg.gif",
"jpeg": "icon_jpg.gif",
"gif": "icon_jpg.gif",
"ico": "icon_jpg.gif",
"bmp": "icon_jpg.gif"
};
return maps[ext] ? maps[ext] : maps['txt'];
}
return {
commands: {
'insertfile': {
execCommand: function (command, filelist) {
filelist = utils.isArray(filelist) ? filelist : [filelist];
var i, item, icon, title,
html = '',
URL = me.getOpt('UEDITOR_HOME_URL'),
iconDir = URL + (URL.substr(URL.length - 1) == '/' ? '' : '/') + 'dialogs/attachment/fileTypeImages/';
for (i = 0; i < filelist.length; i++) {
item = filelist[i];
icon = iconDir + getFileIcon(item.url);
title = item.title || item.url.substr(item.url.lastIndexOf('/') + 1);
html += '' +
' ' +
'' + title + ' ' +
'
';
}
me.execCommand('insertHtml', html);
}
}
}
}
});
// plugins/xssFilter.js
/**
* @file xssFilter.js
* @desc xss过滤器
* @author robbenmu
*/
UE.plugins.xssFilter = function () {
var config = UEDITOR_CONFIG;
var whitList = config.whitList;
function filter(node) {
var tagName = node.tagName;
var attrs = node.attrs;
if (!whitList.hasOwnProperty(tagName)) {
node.parentNode.removeChild(node);
return false;
}
UE.utils.each(attrs, function (val, key) {
if (whitList[tagName].indexOf(key) === -1) {
node.setAttr(key);
}
});
}
// 添加inserthtml\paste等操作用的过滤规则
if (whitList && config.xssFilterRules) {
this.options.filterRules = function () {
var result = {};
UE.utils.each(whitList, function (val, key) {
result[key] = function (node) {
return filter(node);
};
});
return result;
}();
}
var tagList = [];
UE.utils.each(whitList, function (val, key) {
tagList.push(key);
});
// 添加input过滤规则
//
if (whitList && config.inputXssFilter) {
this.addInputRule(function (root) {
root.traversal(function (node) {
if (node.type !== 'element') {
return false;
}
filter(node);
});
});
}
// 添加output过滤规则
//
if (whitList && config.outputXssFilter) {
this.addOutputRule(function (root) {
root.traversal(function (node) {
if (node.type !== 'element') {
return false;
}
filter(node);
});
});
}
};
// ui/ui.js
var baidu = baidu || {};
baidu.editor = baidu.editor || {};
UE.ui = baidu.editor.ui = {};
// ui/uiutils.js
(function () {
var browser = baidu.editor.browser,
domUtils = baidu.editor.dom.domUtils;
var magic = '$EDITORUI';
var root = window[magic] = {};
var uidMagic = 'ID' + magic;
var uidCount = 0;
var uiUtils = baidu.editor.ui.uiUtils = {
uid: function (obj) {
return (obj ? obj[uidMagic] || (obj[uidMagic] = ++uidCount) : ++uidCount);
},
hook: function (fn, callback) {
var dg;
if (fn && fn._callbacks) {
dg = fn;
} else {
dg = function () {
var q;
if (fn) {
q = fn.apply(this, arguments);
}
var callbacks = dg._callbacks;
var k = callbacks.length;
while (k--) {
var r = callbacks[k].apply(this, arguments);
if (q === undefined) {
q = r;
}
}
return q;
};
dg._callbacks = [];
}
dg._callbacks.push(callback);
return dg;
},
createElementByHtml: function (html) {
var el = document.createElement('div');
el.innerHTML = html;
el = el.firstChild;
el.parentNode.removeChild(el);
return el;
},
getViewportElement: function () {
return (browser.ie && browser.quirks) ?
document.body : document.documentElement;
},
getClientRect: function (element) {
var bcr;
//trace IE6下在控制编辑器显隐时可能会报错,catch一下
try {
bcr = element.getBoundingClientRect();
} catch (e) {
bcr = { left: 0, top: 0, height: 0, width: 0 }
}
var rect = {
left: Math.round(bcr.left),
top: Math.round(bcr.top),
height: Math.round(bcr.bottom - bcr.top),
width: Math.round(bcr.right - bcr.left)
};
var doc;
while ((doc = element.ownerDocument) !== document &&
(element = domUtils.getWindow(doc).frameElement)) {
bcr = element.getBoundingClientRect();
rect.left += bcr.left;
rect.top += bcr.top;
}
rect.bottom = rect.top + rect.height;
rect.right = rect.left + rect.width;
return rect;
},
getViewportRect: function () {
var viewportEl = uiUtils.getViewportElement();
var width = (window.innerWidth || viewportEl.clientWidth) | 0;
var height = (window.innerHeight || viewportEl.clientHeight) | 0;
return {
left: 0,
top: 0,
height: height,
width: width,
bottom: height,
right: width
};
},
setViewportOffset: function (element, offset) {
var rect;
var fixedLayer = uiUtils.getFixedLayer();
if (element.parentNode === fixedLayer) {
element.style.left = offset.left + 'px';
element.style.top = offset.top + 'px';
} else {
domUtils.setViewportOffset(element, offset);
}
},
getEventOffset: function (evt) {
var el = evt.target || evt.srcElement;
var rect = uiUtils.getClientRect(el);
var offset = uiUtils.getViewportOffsetByEvent(evt);
return {
left: offset.left - rect.left,
top: offset.top - rect.top
};
},
getViewportOffsetByEvent: function (evt) {
var el = evt.target || evt.srcElement;
var frameEl = domUtils.getWindow(el).frameElement;
var offset = {
left: evt.clientX,
top: evt.clientY
};
if (frameEl && el.ownerDocument !== document) {
var rect = uiUtils.getClientRect(frameEl);
offset.left += rect.left;
offset.top += rect.top;
}
return offset;
},
setGlobal: function (id, obj) {
root[id] = obj;
return magic + '["' + id + '"]';
},
unsetGlobal: function (id) {
delete root[id];
},
copyAttributes: function (tgt, src) {
var attributes = src.attributes;
var k = attributes.length;
while (k--) {
var attrNode = attributes[k];
if (attrNode.nodeName != 'style' && attrNode.nodeName != 'class' && (!browser.ie || attrNode.specified)) {
tgt.setAttribute(attrNode.nodeName, attrNode.nodeValue);
}
}
if (src.className) {
domUtils.addClass(tgt, src.className);
}
if (src.style.cssText) {
tgt.style.cssText += ';' + src.style.cssText;
}
},
removeStyle: function (el, styleName) {
if (el.style.removeProperty) {
el.style.removeProperty(styleName);
} else if (el.style.removeAttribute) {
el.style.removeAttribute(styleName);
} else throw '';
},
contains: function (elA, elB) {
return elA && elB && (elA === elB ? false : (
elA.contains ? elA.contains(elB) :
elA.compareDocumentPosition(elB) & 16
));
},
startDrag: function (evt, callbacks, doc) {
var doc = doc || document;
var startX = evt.clientX;
var startY = evt.clientY;
function handleMouseMove(evt) {
var x = evt.clientX - startX;
var y = evt.clientY - startY;
callbacks.ondragmove(x, y, evt);
if (evt.stopPropagation) {
evt.stopPropagation();
} else {
evt.cancelBubble = true;
}
}
if (doc.addEventListener) {
function handleMouseUp(evt) {
doc.removeEventListener('mousemove', handleMouseMove, true);
doc.removeEventListener('mouseup', handleMouseUp, true);
window.removeEventListener('mouseup', handleMouseUp, true);
callbacks.ondragstop();
}
doc.addEventListener('mousemove', handleMouseMove, true);
doc.addEventListener('mouseup', handleMouseUp, true);
window.addEventListener('mouseup', handleMouseUp, true);
evt.preventDefault();
} else {
var elm = evt.srcElement;
elm.setCapture();
function releaseCaptrue() {
elm.releaseCapture();
elm.detachEvent('onmousemove', handleMouseMove);
elm.detachEvent('onmouseup', releaseCaptrue);
elm.detachEvent('onlosecaptrue', releaseCaptrue);
callbacks.ondragstop();
}
elm.attachEvent('onmousemove', handleMouseMove);
elm.attachEvent('onmouseup', releaseCaptrue);
elm.attachEvent('onlosecaptrue', releaseCaptrue);
evt.returnValue = false;
}
callbacks.ondragstart();
},
getFixedLayer: function () {
var layer = document.getElementById('edui_fixedlayer');
if (layer == null) {
layer = document.createElement('div');
layer.id = 'edui_fixedlayer';
document.body.appendChild(layer);
if (browser.ie && browser.version <= 8) {
layer.style.position = 'absolute';
bindFixedLayer();
setTimeout(updateFixedOffset);
} else {
layer.style.position = 'fixed';
}
layer.style.left = '0';
layer.style.top = '0';
layer.style.width = '0';
layer.style.height = '0';
}
return layer;
},
makeUnselectable: function (element) {
if (browser.opera || (browser.ie && browser.version < 9)) {
element.unselectable = 'on';
if (element.hasChildNodes()) {
for (var i = 0; i < element.childNodes.length; i++) {
if (element.childNodes[i].nodeType == 1) {
uiUtils.makeUnselectable(element.childNodes[i]);
}
}
}
} else {
if (element.style.MozUserSelect !== undefined) {
element.style.MozUserSelect = 'none';
} else if (element.style.WebkitUserSelect !== undefined) {
element.style.WebkitUserSelect = 'none';
} else if (element.style.KhtmlUserSelect !== undefined) {
element.style.KhtmlUserSelect = 'none';
}
}
}
};
function updateFixedOffset() {
var layer = document.getElementById('edui_fixedlayer');
uiUtils.setViewportOffset(layer, {
left: 0,
top: 0
});
// layer.style.display = 'none';
// layer.style.display = 'block';
//#trace: 1354
// setTimeout(updateFixedOffset);
}
function bindFixedLayer(adjOffset) {
domUtils.on(window, 'scroll', updateFixedOffset);
domUtils.on(window, 'resize', baidu.editor.utils.defer(updateFixedOffset, 0, true));
}
})();
// ui/uibase.js
(function () {
var utils = baidu.editor.utils,
uiUtils = baidu.editor.ui.uiUtils,
EventBase = baidu.editor.EventBase,
UIBase = baidu.editor.ui.UIBase = function () {
};
UIBase.prototype = {
className: '',
uiName: '',
initOptions: function (options) {
var me = this;
for (var k in options) {
me[k] = options[k];
}
this.id = this.id || 'edui' + uiUtils.uid();
},
initUIBase: function () {
this._globalKey = utils.unhtml(uiUtils.setGlobal(this.id, this));
},
render: function (holder) {
var html = this.renderHtml();
var el = uiUtils.createElementByHtml(html);
//by xuheng 给每个node添加class
var list = domUtils.getElementsByTagName(el, "*");
var theme = "edui-" + (this.theme || this.editor.options.theme);
var layer = document.getElementById('edui_fixedlayer');
for (var i = 0, node; node = list[i++];) {
domUtils.addClass(node, theme);
}
domUtils.addClass(el, theme);
if (layer) {
layer.className = "";
domUtils.addClass(layer, theme);
}
var seatEl = this.getDom();
if (seatEl != null) {
seatEl.parentNode.replaceChild(el, seatEl);
uiUtils.copyAttributes(el, seatEl);
} else {
if (typeof holder == 'string') {
holder = document.getElementById(holder);
}
holder = holder || uiUtils.getFixedLayer();
domUtils.addClass(holder, theme);
holder.appendChild(el);
}
this.postRender();
},
getDom: function (name) {
if (!name) {
return document.getElementById(this.id);
} else {
return document.getElementById(this.id + '_' + name);
}
},
postRender: function () {
this.fireEvent('postrender');
},
getHtmlTpl: function () {
return '';
},
formatHtml: function (tpl) {
var prefix = 'edui-' + this.uiName;
return (tpl
.replace(/##/g, this.id)
.replace(/%%-/g, this.uiName ? prefix + '-' : '')
.replace(/%%/g, (this.uiName ? prefix : '') + ' ' + this.className)
.replace(/\$\$/g, this._globalKey));
},
renderHtml: function () {
return this.formatHtml(this.getHtmlTpl());
},
dispose: function () {
var box = this.getDom();
if (box) baidu.editor.dom.domUtils.remove(box);
uiUtils.unsetGlobal(this.id);
}
};
utils.inherits(UIBase, EventBase);
})();
// ui/separator.js
(function () {
var utils = baidu.editor.utils,
UIBase = baidu.editor.ui.UIBase,
Separator = baidu.editor.ui.Separator = function (options) {
this.initOptions(options);
this.initSeparator();
};
Separator.prototype = {
uiName: 'separator',
initSeparator: function () {
this.initUIBase();
},
getHtmlTpl: function () {
return '
';
}
};
utils.inherits(Separator, UIBase);
})();
// ui/mask.js
///import core
///import uicore
(function () {
var utils = baidu.editor.utils,
domUtils = baidu.editor.dom.domUtils,
UIBase = baidu.editor.ui.UIBase,
uiUtils = baidu.editor.ui.uiUtils;
var Mask = baidu.editor.ui.Mask = function (options) {
this.initOptions(options);
this.initUIBase();
};
Mask.prototype = {
getHtmlTpl: function () {
return '
';
},
postRender: function () {
var me = this;
domUtils.on(window, 'resize', function () {
setTimeout(function () {
if (!me.isHidden()) {
me._fill();
}
});
});
},
show: function (zIndex) {
this._fill();
this.getDom().style.display = '';
this.getDom().style.zIndex = zIndex;
},
hide: function () {
this.getDom().style.display = 'none';
this.getDom().style.zIndex = '';
},
isHidden: function () {
return this.getDom().style.display == 'none';
},
_onMouseDown: function () {
return false;
},
_onClick: function (e, target) {
this.fireEvent('click', e, target);
},
_fill: function () {
var el = this.getDom();
var vpRect = uiUtils.getViewportRect();
el.style.width = vpRect.width + 'px';
el.style.height = vpRect.height + 'px';
}
};
utils.inherits(Mask, UIBase);
})();
// ui/popup.js
///import core
///import uicore
(function () {
var utils = baidu.editor.utils,
uiUtils = baidu.editor.ui.uiUtils,
domUtils = baidu.editor.dom.domUtils,
UIBase = baidu.editor.ui.UIBase,
Popup = baidu.editor.ui.Popup = function (options) {
this.initOptions(options);
this.initPopup();
};
var allPopups = [];
function closeAllPopup(evt, el) {
for (var i = 0; i < allPopups.length; i++) {
var pop = allPopups[i];
if (!pop.isHidden()) {
if (pop.queryAutoHide(el) !== false) {
if (evt && /scroll/ig.test(evt.type) && pop.className == "edui-wordpastepop") return;
pop.hide();
}
}
}
if (allPopups.length)
pop.editor.fireEvent("afterhidepop");
}
Popup.postHide = closeAllPopup;
var ANCHOR_CLASSES = ['edui-anchor-topleft', 'edui-anchor-topright',
'edui-anchor-bottomleft', 'edui-anchor-bottomright'];
Popup.prototype = {
SHADOW_RADIUS: 5,
content: null,
_hidden: false,
autoRender: true,
canSideLeft: true,
canSideUp: true,
initPopup: function () {
this.initUIBase();
allPopups.push(this);
},
getHtmlTpl: function () {
return '';
},
getContentHtmlTpl: function () {
if (this.content) {
if (typeof this.content == 'string') {
return this.content;
}
return this.content.renderHtml();
} else {
return ''
}
},
_UIBase_postRender: UIBase.prototype.postRender,
postRender: function () {
if (this.content instanceof UIBase) {
this.content.postRender();
}
//捕获鼠标滚轮
if (this.captureWheel && !this.captured) {
this.captured = true;
var winHeight = (document.documentElement.clientHeight || document.body.clientHeight) - 80,
_height = this.getDom().offsetHeight,
_top = uiUtils.getClientRect(this.combox.getDom()).top,
content = this.getDom('content'),
ifr = this.getDom('body').getElementsByTagName('iframe'),
me = this;
ifr.length && (ifr = ifr[0]);
while (_top + _height > winHeight) {
_height -= 30;
}
content.style.height = _height + 'px';
//同步更改iframe高度
ifr && (ifr.style.height = _height + 'px');
//阻止在combox上的鼠标滚轮事件, 防止用户的正常操作被误解
if (window.XMLHttpRequest) {
domUtils.on(content, ('onmousewheel' in document.body) ? 'mousewheel' : 'DOMMouseScroll', function (e) {
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
if (e.wheelDelta) {
content.scrollTop -= (e.wheelDelta / 120) * 60;
} else {
content.scrollTop -= (e.detail / -3) * 60;
}
});
} else {
//ie6
domUtils.on(this.getDom(), 'mousewheel', function (e) {
e.returnValue = false;
me.getDom('content').scrollTop -= (e.wheelDelta / 120) * 60;
});
}
}
this.fireEvent('postRenderAfter');
this.hide(true);
this._UIBase_postRender();
},
_doAutoRender: function () {
if (!this.getDom() && this.autoRender) {
this.render();
}
},
mesureSize: function () {
var box = this.getDom('content');
return uiUtils.getClientRect(box);
},
fitSize: function () {
if (this.captureWheel && this.sized) {
return this.__size;
}
this.sized = true;
var popBodyEl = this.getDom('body');
popBodyEl.style.width = '';
popBodyEl.style.height = '';
var size = this.mesureSize();
if (this.captureWheel) {
popBodyEl.style.width = -(-20 - size.width) + 'px';
var height = parseInt(this.getDom('content').style.height, 10);
!window.isNaN(height) && (size.height = height);
} else {
popBodyEl.style.width = size.width + 'px';
}
popBodyEl.style.height = size.height + 'px';
this.__size = size;
this.captureWheel && (this.getDom('content').style.overflow = 'auto');
return size;
},
showAnchor: function (element, hoz) {
this.showAnchorRect(uiUtils.getClientRect(element), hoz);
},
showAnchorRect: function (rect, hoz, adj) {
this._doAutoRender();
var vpRect = uiUtils.getViewportRect();
this.getDom().style.visibility = 'hidden';
this._show();
var popSize = this.fitSize();
var sideLeft, sideUp, left, top;
if (hoz) {
sideLeft = this.canSideLeft && (rect.right + popSize.width > vpRect.right && rect.left > popSize.width);
sideUp = this.canSideUp && (rect.top + popSize.height > vpRect.bottom && rect.bottom > popSize.height);
left = (sideLeft ? rect.left - popSize.width : rect.right);
top = (sideUp ? rect.bottom - popSize.height : rect.top);
} else {
sideLeft = this.canSideLeft && (rect.right + popSize.width > vpRect.right && rect.left > popSize.width);
sideUp = this.canSideUp && (rect.top + popSize.height > vpRect.bottom && rect.bottom > popSize.height);
left = (sideLeft ? rect.right - popSize.width : rect.left);
top = (sideUp ? rect.top - popSize.height : rect.bottom);
}
var popEl = this.getDom();
uiUtils.setViewportOffset(popEl, {
left: left,
top: top
});
domUtils.removeClasses(popEl, ANCHOR_CLASSES);
popEl.className += ' ' + ANCHOR_CLASSES[(sideUp ? 1 : 0) * 2 + (sideLeft ? 1 : 0)];
if (this.editor) {
popEl.style.zIndex = this.editor.container.style.zIndex * 1 + 10;
baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = popEl.style.zIndex - 1;
}
this.getDom().style.visibility = 'visible';
},
showAt: function (offset) {
var left = offset.left;
var top = offset.top;
var rect = {
left: left,
top: top,
right: left,
bottom: top,
height: 0,
width: 0
};
this.showAnchorRect(rect, false, true);
},
_show: function () {
if (this._hidden) {
var box = this.getDom();
box.style.display = '';
this._hidden = false;
// if (box.setActive) {
// box.setActive();
// }
this.fireEvent('show');
}
},
isHidden: function () {
return this._hidden;
},
show: function () {
this._doAutoRender();
this._show();
},
hide: function (notNofity) {
if (!this._hidden && this.getDom()) {
this.getDom().style.display = 'none';
this._hidden = true;
if (!notNofity) {
this.fireEvent('hide');
}
}
},
queryAutoHide: function (el) {
return !el || !uiUtils.contains(this.getDom(), el);
}
};
utils.inherits(Popup, UIBase);
domUtils.on(document, 'mousedown', function (evt) {
var el = evt.target || evt.srcElement;
closeAllPopup(evt, el);
});
domUtils.on(window, 'scroll', function (evt, el) {
closeAllPopup(evt, el);
});
})();
// ui/colorpicker.js
///import core
///import uicore
(function () {
var utils = baidu.editor.utils,
UIBase = baidu.editor.ui.UIBase,
ColorPicker = baidu.editor.ui.ColorPicker = function (options) {
this.initOptions(options);
this.noColorText = this.noColorText || this.editor.getLang("clearColor");
this.initUIBase();
};
ColorPicker.prototype = {
getHtmlTpl: function () {
return genColorPicker(this.noColorText, this.editor);
},
_onTableClick: function (evt) {
var tgt = evt.target || evt.srcElement;
var color = tgt.getAttribute('data-color');
if (color) {
this.fireEvent('pickcolor', color);
}
},
_onTableOver: function (evt) {
var tgt = evt.target || evt.srcElement;
var color = tgt.getAttribute('data-color');
if (color) {
this.getDom('preview').style.backgroundColor = color;
}
},
_onTableOut: function () {
this.getDom('preview').style.backgroundColor = '';
},
_onPickNoColor: function () {
this.fireEvent('picknocolor');
}
};
utils.inherits(ColorPicker, UIBase);
var COLORS = (
'ffffff,000000,eeece1,1f497d,4f81bd,c0504d,9bbb59,8064a2,4bacc6,f79646,' +
'f2f2f2,7f7f7f,ddd9c3,c6d9f0,dbe5f1,f2dcdb,ebf1dd,e5e0ec,dbeef3,fdeada,' +
'd8d8d8,595959,c4bd97,8db3e2,b8cce4,e5b9b7,d7e3bc,ccc1d9,b7dde8,fbd5b5,' +
'bfbfbf,3f3f3f,938953,548dd4,95b3d7,d99694,c3d69b,b2a2c7,92cddc,fac08f,' +
'a5a5a5,262626,494429,17365d,366092,953734,76923c,5f497a,31859b,e36c09,' +
'7f7f7f,0c0c0c,1d1b10,0f243e,244061,632423,4f6128,3f3151,205867,974806,' +
'c00000,ff0000,ffc000,ffff00,92d050,00b050,00b0f0,0070c0,002060,7030a0,').split(',');
function genColorPicker(noColorText, editor) {
var html = '' +
'
' +
'
' +
'
' + noColorText + '
' +
'
' +
'
' +
'' + editor.getLang("themeColor") + ' ' +
'';
for (var i = 0; i < COLORS.length; i++) {
if (i && i % 10 === 0) {
html += ' ' + (i == 60 ? '' + editor.getLang("standardColor") + ' ' : '') + '';
}
html += i < 70 ? ' ' : '';
}
html += '
';
return html;
}
})();
// ui/tablepicker.js
///import core
///import uicore
(function () {
var utils = baidu.editor.utils,
uiUtils = baidu.editor.ui.uiUtils,
UIBase = baidu.editor.ui.UIBase;
var TablePicker = baidu.editor.ui.TablePicker = function (options) {
this.initOptions(options);
this.initTablePicker();
};
TablePicker.prototype = {
defaultNumRows: 10,
defaultNumCols: 10,
maxNumRows: 20,
maxNumCols: 20,
numRows: 10,
numCols: 10,
lengthOfCellSide: 22,
initTablePicker: function () {
this.initUIBase();
},
getHtmlTpl: function () {
var me = this;
return '' +
'
' +
'
' +
' ' +
'
' +
'
' +
'
' +
'
';
},
_UIBase_render: UIBase.prototype.render,
render: function (holder) {
this._UIBase_render(holder);
this.getDom('label').innerHTML = '0' + this.editor.getLang("t_row") + ' x 0' + this.editor.getLang("t_col");
},
_track: function (numCols, numRows) {
var style = this.getDom('overlay').style;
var sideLen = this.lengthOfCellSide;
style.width = numCols * sideLen + 'px';
style.height = numRows * sideLen + 'px';
var label = this.getDom('label');
label.innerHTML = numCols + this.editor.getLang("t_col") + ' x ' + numRows + this.editor.getLang("t_row");
this.numCols = numCols;
this.numRows = numRows;
},
_onMouseOver: function (evt, el) {
var rel = evt.relatedTarget || evt.fromElement;
if (!uiUtils.contains(el, rel) && el !== rel) {
this.getDom('label').innerHTML = '0' + this.editor.getLang("t_col") + ' x 0' + this.editor.getLang("t_row");
this.getDom('overlay').style.visibility = '';
}
},
_onMouseOut: function (evt, el) {
var rel = evt.relatedTarget || evt.toElement;
if (!uiUtils.contains(el, rel) && el !== rel) {
this.getDom('label').innerHTML = '0' + this.editor.getLang("t_col") + ' x 0' + this.editor.getLang("t_row");
this.getDom('overlay').style.visibility = 'hidden';
}
},
_onMouseMove: function (evt, el) {
var style = this.getDom('overlay').style;
var offset = uiUtils.getEventOffset(evt);
var sideLen = this.lengthOfCellSide;
var numCols = Math.ceil(offset.left / sideLen);
var numRows = Math.ceil(offset.top / sideLen);
this._track(numCols, numRows);
},
_onClick: function () {
this.fireEvent('picktable', this.numCols, this.numRows);
}
};
utils.inherits(TablePicker, UIBase);
})();
// ui/stateful.js
(function () {
var browser = baidu.editor.browser,
domUtils = baidu.editor.dom.domUtils,
uiUtils = baidu.editor.ui.uiUtils;
var TPL_STATEFUL = 'onmousedown="$$.Stateful_onMouseDown(event, this);"' +
' onmouseup="$$.Stateful_onMouseUp(event, this);"' +
(browser.ie ? (
' onmouseenter="$$.Stateful_onMouseEnter(event, this);"' +
' onmouseleave="$$.Stateful_onMouseLeave(event, this);"')
: (
' onmouseover="$$.Stateful_onMouseOver(event, this);"' +
' onmouseout="$$.Stateful_onMouseOut(event, this);"'));
baidu.editor.ui.Stateful = {
alwalysHoverable: false,
target: null,//目标元素和this指向dom不一样
Stateful_init: function () {
this._Stateful_dGetHtmlTpl = this.getHtmlTpl;
this.getHtmlTpl = this.Stateful_getHtmlTpl;
},
Stateful_getHtmlTpl: function () {
var tpl = this._Stateful_dGetHtmlTpl();
// 使用function避免$转义
return tpl.replace(/stateful/g, function () { return TPL_STATEFUL; });
},
Stateful_onMouseEnter: function (evt, el) {
this.target = el;
if (!this.isDisabled() || this.alwalysHoverable) {
this.addState('hover');
this.fireEvent('over');
}
},
Stateful_onMouseLeave: function (evt, el) {
if (!this.isDisabled() || this.alwalysHoverable) {
this.removeState('hover');
this.removeState('active');
this.fireEvent('out');
}
},
Stateful_onMouseOver: function (evt, el) {
var rel = evt.relatedTarget;
if (!uiUtils.contains(el, rel) && el !== rel) {
this.Stateful_onMouseEnter(evt, el);
}
},
Stateful_onMouseOut: function (evt, el) {
var rel = evt.relatedTarget;
if (!uiUtils.contains(el, rel) && el !== rel) {
this.Stateful_onMouseLeave(evt, el);
}
},
Stateful_onMouseDown: function (evt, el) {
if (!this.isDisabled()) {
this.addState('active');
}
},
Stateful_onMouseUp: function (evt, el) {
if (!this.isDisabled()) {
this.removeState('active');
}
},
Stateful_postRender: function () {
if (this.disabled && !this.hasState('disabled')) {
this.addState('disabled');
}
},
hasState: function (state) {
return domUtils.hasClass(this.getStateDom(), 'edui-state-' + state);
},
addState: function (state) {
if (!this.hasState(state)) {
this.getStateDom().className += ' edui-state-' + state;
}
},
removeState: function (state) {
if (this.hasState(state)) {
domUtils.removeClasses(this.getStateDom(), ['edui-state-' + state]);
}
},
getStateDom: function () {
return this.getDom('state');
},
isChecked: function () {
return this.hasState('checked');
},
setChecked: function (checked) {
if (!this.isDisabled() && checked) {
this.addState('checked');
} else {
this.removeState('checked');
}
},
isDisabled: function () {
return this.hasState('disabled');
},
setDisabled: function (disabled) {
if (disabled) {
this.removeState('hover');
this.removeState('checked');
this.removeState('active');
this.addState('disabled');
} else {
this.removeState('disabled');
}
}
};
})();
// ui/button.js
///import core
///import uicore
///import ui/stateful.js
(function () {
var utils = baidu.editor.utils,
UIBase = baidu.editor.ui.UIBase,
Stateful = baidu.editor.ui.Stateful,
Button = baidu.editor.ui.Button = function (options) {
if (options.name) {
var btnName = options.name;
var cssRules = options.cssRules;
if (!options.className) {
options.className = 'edui-for-' + btnName;
}
options.cssRules = '.edui-default .edui-for-' + btnName + ' .edui-icon {' + cssRules + '}'
}
this.initOptions(options);
this.initButton();
};
Button.prototype = {
uiName: 'button',
label: '',
title: '',
showIcon: true,
showText: true,
cssRules: '',
initButton: function () {
this.initUIBase();
this.Stateful_init();
if (this.cssRules) {
utils.cssRule('edui-customize-' + this.name + '-style', this.cssRules);
}
},
getHtmlTpl: function () {
return '' +
'
' +
'
' +
(this.showIcon ? '
' : '') +
(this.showText ? '
' + this.label + '
' : '') +
'
' +
'
' +
'
';
},
postRender: function () {
this.Stateful_postRender();
this.setDisabled(this.disabled)
},
_onMouseDown: function (e) {
var target = e.target || e.srcElement,
tagName = target && target.tagName && target.tagName.toLowerCase();
if (tagName == 'input' || tagName == 'object' || tagName == 'object') {
return false;
}
},
_onClick: function () {
if (!this.isDisabled()) {
this.fireEvent('click');
}
},
setTitle: function (text) {
var label = this.getDom('label');
label.innerHTML = text;
}
};
utils.inherits(Button, UIBase);
utils.extend(Button.prototype, Stateful);
})();
// ui/splitbutton.js
///import core
///import uicore
///import ui/stateful.js
(function () {
var utils = baidu.editor.utils,
uiUtils = baidu.editor.ui.uiUtils,
domUtils = baidu.editor.dom.domUtils,
UIBase = baidu.editor.ui.UIBase,
Stateful = baidu.editor.ui.Stateful,
SplitButton = baidu.editor.ui.SplitButton = function (options) {
this.initOptions(options);
this.initSplitButton();
};
SplitButton.prototype = {
popup: null,
uiName: 'splitbutton',
title: '',
initSplitButton: function () {
this.initUIBase();
this.Stateful_init();
var me = this;
if (this.popup != null) {
var popup = this.popup;
this.popup = null;
this.setPopup(popup);
}
},
_UIBase_postRender: UIBase.prototype.postRender,
postRender: function () {
this.Stateful_postRender();
this._UIBase_postRender();
},
setPopup: function (popup) {
if (this.popup === popup) return;
if (this.popup != null) {
this.popup.dispose();
}
popup.addListener('show', utils.bind(this._onPopupShow, this));
popup.addListener('hide', utils.bind(this._onPopupHide, this));
popup.addListener('postrender', utils.bind(function () {
popup.getDom('body').appendChild(
uiUtils.createElementByHtml('')
);
popup.getDom().className += ' ' + this.className;
}, this));
this.popup = popup;
},
_onPopupShow: function () {
this.addState('opened');
},
_onPopupHide: function () {
this.removeState('opened');
},
getHtmlTpl: function () {
return '';
},
showPopup: function () {
// 当popup往上弹出的时候,做特殊处理
var rect = uiUtils.getClientRect(this.getDom());
rect.top -= this.popup.SHADOW_RADIUS;
rect.height += this.popup.SHADOW_RADIUS;
this.popup.showAnchorRect(rect);
},
_onArrowClick: function (event, el) {
if (!this.isDisabled()) {
this.showPopup();
}
},
_onButtonClick: function () {
if (!this.isDisabled()) {
this.fireEvent('buttonclick');
}
}
};
utils.inherits(SplitButton, UIBase);
utils.extend(SplitButton.prototype, Stateful, true);
})();
// ui/colorbutton.js
///import core
///import uicore
///import ui/colorpicker.js
///import ui/popup.js
///import ui/splitbutton.js
(function () {
var utils = baidu.editor.utils,
uiUtils = baidu.editor.ui.uiUtils,
ColorPicker = baidu.editor.ui.ColorPicker,
Popup = baidu.editor.ui.Popup,
SplitButton = baidu.editor.ui.SplitButton,
ColorButton = baidu.editor.ui.ColorButton = function (options) {
this.initOptions(options);
this.initColorButton();
};
ColorButton.prototype = {
initColorButton: function () {
var me = this;
this.popup = new Popup({
content: new ColorPicker({
noColorText: me.editor.getLang("clearColor"),
editor: me.editor,
onpickcolor: function (t, color) {
me._onPickColor(color);
},
onpicknocolor: function (t, color) {
me._onPickNoColor(color);
}
}),
editor: me.editor
});
this.initSplitButton();
},
_SplitButton_postRender: SplitButton.prototype.postRender,
postRender: function () {
this._SplitButton_postRender();
this.getDom('button_body').appendChild(
uiUtils.createElementByHtml('
')
);
this.getDom().className += ' edui-colorbutton';
},
setColor: function (color) {
this.getDom('colorlump').style.backgroundColor = color;
this.color = color;
},
_onPickColor: function (color) {
if (this.fireEvent('pickcolor', color) !== false) {
this.setColor(color);
this.popup.hide();
}
},
_onPickNoColor: function (color) {
if (this.fireEvent('picknocolor') !== false) {
this.popup.hide();
}
}
};
utils.inherits(ColorButton, SplitButton);
})();
// ui/tablebutton.js
///import core
///import uicore
///import ui/popup.js
///import ui/tablepicker.js
///import ui/splitbutton.js
(function () {
var utils = baidu.editor.utils,
Popup = baidu.editor.ui.Popup,
TablePicker = baidu.editor.ui.TablePicker,
SplitButton = baidu.editor.ui.SplitButton,
TableButton = baidu.editor.ui.TableButton = function (options) {
this.initOptions(options);
this.initTableButton();
};
TableButton.prototype = {
initTableButton: function () {
var me = this;
this.popup = new Popup({
content: new TablePicker({
editor: me.editor,
onpicktable: function (t, numCols, numRows) {
me._onPickTable(numCols, numRows);
}
}),
'editor': me.editor
});
this.initSplitButton();
},
_onPickTable: function (numCols, numRows) {
if (this.fireEvent('picktable', numCols, numRows) !== false) {
this.popup.hide();
}
}
};
utils.inherits(TableButton, SplitButton);
})();
// ui/autotypesetpicker.js
///import core
///import uicore
(function () {
var utils = baidu.editor.utils,
UIBase = baidu.editor.ui.UIBase;
var AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker = function (options) {
this.initOptions(options);
this.initAutoTypeSetPicker();
};
AutoTypeSetPicker.prototype = {
initAutoTypeSetPicker: function () {
this.initUIBase();
},
getHtmlTpl: function () {
var me = this.editor,
opt = me.options.autotypeset,
lang = me.getLang("autoTypeSet");
var textAlignInputName = 'textAlignValue' + me.uid,
imageBlockInputName = 'imageBlockLineValue' + me.uid,
symbolConverInputName = 'symbolConverValue' + me.uid;
return '';
},
_UIBase_render: UIBase.prototype.render
};
utils.inherits(AutoTypeSetPicker, UIBase);
})();
// ui/autotypesetbutton.js
///import core
///import uicore
///import ui/popup.js
///import ui/autotypesetpicker.js
///import ui/splitbutton.js
(function () {
var utils = baidu.editor.utils,
Popup = baidu.editor.ui.Popup,
AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker,
SplitButton = baidu.editor.ui.SplitButton,
AutoTypeSetButton = baidu.editor.ui.AutoTypeSetButton = function (options) {
this.initOptions(options);
this.initAutoTypeSetButton();
};
function getPara(me) {
var opt = {},
cont = me.getDom(),
editorId = me.editor.uid,
inputType = null,
attrName = null,
ipts = domUtils.getElementsByTagName(cont, "input");
for (var i = ipts.length - 1, ipt; ipt = ipts[i--];) {
inputType = ipt.getAttribute("type");
if (inputType == "checkbox") {
attrName = ipt.getAttribute("name");
opt[attrName] && delete opt[attrName];
if (ipt.checked) {
var attrValue = document.getElementById(attrName + "Value" + editorId);
if (attrValue) {
if (/input/ig.test(attrValue.tagName)) {
opt[attrName] = attrValue.value;
} else {
var iptChilds = attrValue.getElementsByTagName("input");
for (var j = iptChilds.length - 1, iptchild; iptchild = iptChilds[j--];) {
if (iptchild.checked) {
opt[attrName] = iptchild.value;
break;
}
}
}
} else {
opt[attrName] = true;
}
} else {
opt[attrName] = false;
}
} else {
opt[ipt.getAttribute("value")] = ipt.checked;
}
}
var selects = domUtils.getElementsByTagName(cont, "select");
for (var i = 0, si; si = selects[i++];) {
var attr = si.getAttribute('name');
opt[attr] = opt[attr] ? si.value : '';
}
utils.extend(me.editor.options.autotypeset, opt);
me.editor.setPreferences('autotypeset', opt);
}
AutoTypeSetButton.prototype = {
initAutoTypeSetButton: function () {
var me = this;
this.popup = new Popup({
//传入配置参数
content: new AutoTypeSetPicker({ editor: me.editor }),
'editor': me.editor,
hide: function () {
if (!this._hidden && this.getDom()) {
getPara(this);
this.getDom().style.display = 'none';
this._hidden = true;
this.fireEvent('hide');
}
}
});
var flag = 0;
this.popup.addListener('postRenderAfter', function () {
var popupUI = this;
if (flag) return;
var cont = this.getDom(),
btn = cont.getElementsByTagName('button')[0];
btn.onclick = function () {
getPara(popupUI);
me.editor.execCommand('autotypeset');
popupUI.hide()
};
domUtils.on(cont, 'click', function (e) {
var target = e.target || e.srcElement,
editorId = me.editor.uid;
if (target && target.tagName == 'INPUT') {
// 点击图片浮动的checkbox,去除对应的radio
if (target.name == 'imageBlockLine' || target.name == 'textAlign' || target.name == 'symbolConver') {
var checked = target.checked,
radioTd = document.getElementById(target.name + 'Value' + editorId),
radios = radioTd.getElementsByTagName('input'),
defalutSelect = {
'imageBlockLine': 'none',
'textAlign': 'left',
'symbolConver': 'tobdc'
};
for (var i = 0; i < radios.length; i++) {
if (checked) {
if (radios[i].value == defalutSelect[target.name]) {
radios[i].checked = 'checked';
}
} else {
radios[i].checked = false;
}
}
}
// 点击radio,选中对应的checkbox
if (target.name == ('imageBlockLineValue' + editorId) || target.name == ('textAlignValue' + editorId) || target.name == 'bdc') {
var checkboxs = target.parentNode.previousSibling.getElementsByTagName('input');
checkboxs && (checkboxs[0].checked = true);
}
getPara(popupUI);
}
});
flag = 1;
});
this.initSplitButton();
}
};
utils.inherits(AutoTypeSetButton, SplitButton);
})();
// ui/cellalignpicker.js
///import core
///import uicore
(function () {
var utils = baidu.editor.utils,
Popup = baidu.editor.ui.Popup,
Stateful = baidu.editor.ui.Stateful,
UIBase = baidu.editor.ui.UIBase;
/**
* 该参数将新增一个参数: selected, 参数类型为一个Object, 形如{ 'align': 'center', 'valign': 'top' }, 表示单元格的初始
* 对齐状态为: 竖直居上,水平居中; 其中 align的取值为:'center', 'left', 'right'; valign的取值为: 'top', 'middle', 'bottom'
* @update 2013/4/2 hancong03@baidu.com
*/
var CellAlignPicker = baidu.editor.ui.CellAlignPicker = function (options) {
this.initOptions(options);
this.initSelected();
this.initCellAlignPicker();
};
CellAlignPicker.prototype = {
//初始化选中状态, 该方法将根据传递进来的参数获取到应该选中的对齐方式图标的索引
initSelected: function () {
var status = {
valign: {
top: 0,
middle: 1,
bottom: 2
},
align: {
left: 0,
center: 1,
right: 2
},
count: 3
},
result = -1;
if (this.selected) {
this.selectedIndex = status.valign[this.selected.valign] * status.count + status.align[this.selected.align];
}
},
initCellAlignPicker: function () {
this.initUIBase();
this.Stateful_init();
},
getHtmlTpl: function () {
var alignType = ['left', 'center', 'right'],
COUNT = 9,
tempClassName = null,
tempIndex = -1,
tmpl = [];
for (var i = 0; i < COUNT; i++) {
tempClassName = this.selectedIndex === i ? ' class="edui-cellalign-selected" ' : '';
tempIndex = i % 3;
tempIndex === 0 && tmpl.push('');
tmpl.push('
');
tempIndex === 2 && tmpl.push(' ');
}
return '';
},
getStateDom: function () {
return this.target;
},
_onClick: function (evt) {
var target = evt.target || evt.srcElement;
if (/icon/.test(target.className)) {
this.items[target.parentNode.getAttribute("index")].onclick();
Popup.postHide(evt);
}
},
_UIBase_render: UIBase.prototype.render
};
utils.inherits(CellAlignPicker, UIBase);
utils.extend(CellAlignPicker.prototype, Stateful, true);
})();
// ui/pastepicker.js
///import core
///import uicore
(function () {
var utils = baidu.editor.utils,
Stateful = baidu.editor.ui.Stateful,
uiUtils = baidu.editor.ui.uiUtils,
UIBase = baidu.editor.ui.UIBase;
var PastePicker = baidu.editor.ui.PastePicker = function (options) {
this.initOptions(options);
this.initPastePicker();
};
PastePicker.prototype = {
initPastePicker: function () {
this.initUIBase();
this.Stateful_init();
},
getHtmlTpl: function () {
return '
' +
'' +
'
' + this.editor.getLang("pasteOpt") + '
' +
'
' +
'
' +
''
},
getStateDom: function () {
return this.target;
},
format: function (param) {
this.editor.ui._isTransfer = true;
this.editor.fireEvent('pasteTransfer', param);
},
_onClick: function (cur) {
var node = domUtils.getNextDomNode(cur),
screenHt = uiUtils.getViewportRect().height,
subPop = uiUtils.getClientRect(node);
if ((subPop.top + subPop.height) > screenHt)
node.style.top = (-subPop.height - cur.offsetHeight) + "px";
else
node.style.top = "";
if (/hidden/ig.test(domUtils.getComputedStyle(node, "visibility"))) {
node.style.visibility = "visible";
domUtils.addClass(cur, "edui-state-opened");
} else {
node.style.visibility = "hidden";
domUtils.removeClasses(cur, "edui-state-opened")
}
},
_UIBase_render: UIBase.prototype.render
};
utils.inherits(PastePicker, UIBase);
utils.extend(PastePicker.prototype, Stateful, true);
})();
// ui/toolbar.js
(function () {
var utils = baidu.editor.utils,
uiUtils = baidu.editor.ui.uiUtils,
UIBase = baidu.editor.ui.UIBase,
Toolbar = baidu.editor.ui.Toolbar = function (options) {
this.initOptions(options);
this.initToolbar();
};
Toolbar.prototype = {
items: null,
initToolbar: function () {
this.items = this.items || [];
this.initUIBase();
},
add: function (item, index) {
if (index === undefined) {
this.items.push(item);
} else {
this.items.splice(index, 0, item)
}
},
getHtmlTpl: function () {
var buff = [];
for (var i = 0; i < this.items.length; i++) {
buff[i] = this.items[i].renderHtml();
}
return '' +
buff.join('') +
'
'
},
postRender: function () {
var box = this.getDom();
for (var i = 0; i < this.items.length; i++) {
this.items[i].postRender();
}
uiUtils.makeUnselectable(box);
},
_onMouseDown: function (e) {
var target = e.target || e.srcElement,
tagName = target && target.tagName && target.tagName.toLowerCase();
if (tagName == 'input' || tagName == 'object' || tagName == 'object') {
return false;
}
}
};
utils.inherits(Toolbar, UIBase);
})();
// ui/menu.js
///import core
///import uicore
///import ui\popup.js
///import ui\stateful.js
(function () {
var utils = baidu.editor.utils,
domUtils = baidu.editor.dom.domUtils,
uiUtils = baidu.editor.ui.uiUtils,
UIBase = baidu.editor.ui.UIBase,
Popup = baidu.editor.ui.Popup,
Stateful = baidu.editor.ui.Stateful,
CellAlignPicker = baidu.editor.ui.CellAlignPicker,
Menu = baidu.editor.ui.Menu = function (options) {
this.initOptions(options);
this.initMenu();
};
var menuSeparator = {
renderHtml: function () {
return '';
},
postRender: function () {
},
queryAutoHide: function () {
return true;
}
};
Menu.prototype = {
items: null,
uiName: 'menu',
initMenu: function () {
this.items = this.items || [];
this.initPopup();
this.initItems();
},
initItems: function () {
for (var i = 0; i < this.items.length; i++) {
var item = this.items[i];
if (item == '-') {
this.items[i] = this.getSeparator();
} else if (!(item instanceof MenuItem)) {
item.editor = this.editor;
item.theme = this.editor.options.theme;
this.items[i] = this.createItem(item);
}
}
},
getSeparator: function () {
return menuSeparator;
},
createItem: function (item) {
//新增一个参数menu, 该参数存储了menuItem所对应的menu引用
item.menu = this;
return new MenuItem(item);
},
_Popup_getContentHtmlTpl: Popup.prototype.getContentHtmlTpl,
getContentHtmlTpl: function () {
if (this.items.length == 0) {
return this._Popup_getContentHtmlTpl();
}
var buff = [];
for (var i = 0; i < this.items.length; i++) {
var item = this.items[i];
buff[i] = item.renderHtml();
}
return ('' + buff.join('') + '
');
},
_Popup_postRender: Popup.prototype.postRender,
postRender: function () {
var me = this;
for (var i = 0; i < this.items.length; i++) {
var item = this.items[i];
item.ownerMenu = this;
item.postRender();
}
domUtils.on(this.getDom(), 'mouseover', function (evt) {
evt = evt || event;
var rel = evt.relatedTarget || evt.fromElement;
var el = me.getDom();
if (!uiUtils.contains(el, rel) && el !== rel) {
me.fireEvent('over');
}
});
this._Popup_postRender();
},
queryAutoHide: function (el) {
if (el) {
if (uiUtils.contains(this.getDom(), el)) {
return false;
}
for (var i = 0; i < this.items.length; i++) {
var item = this.items[i];
if (item.queryAutoHide(el) === false) {
return false;
}
}
}
},
clearItems: function () {
for (var i = 0; i < this.items.length; i++) {
var item = this.items[i];
clearTimeout(item._showingTimer);
clearTimeout(item._closingTimer);
if (item.subMenu) {
item.subMenu.destroy();
}
}
this.items = [];
},
destroy: function () {
if (this.getDom()) {
domUtils.remove(this.getDom());
}
this.clearItems();
},
dispose: function () {
this.destroy();
}
};
utils.inherits(Menu, Popup);
/**
* @update 2013/04/03 hancong03 新增一个参数menu, 该参数存储了menuItem所对应的menu引用
* @type {Function}
*/
var MenuItem = baidu.editor.ui.MenuItem = function (options) {
this.initOptions(options);
this.initUIBase();
this.Stateful_init();
if (this.subMenu && !(this.subMenu instanceof Menu)) {
if (options.className && options.className.indexOf("aligntd") != -1) {
var me = this;
//获取单元格对齐初始状态
this.subMenu.selected = this.editor.queryCommandValue('cellalignment');
this.subMenu = new Popup({
content: new CellAlignPicker(this.subMenu),
parentMenu: me,
editor: me.editor,
destroy: function () {
if (this.getDom()) {
domUtils.remove(this.getDom());
}
}
});
this.subMenu.addListener("postRenderAfter", function () {
domUtils.on(this.getDom(), "mouseover", function () {
me.addState('opened');
});
});
} else {
this.subMenu = new Menu(this.subMenu);
}
}
};
MenuItem.prototype = {
label: '',
subMenu: null,
ownerMenu: null,
uiName: 'menuitem',
alwalysHoverable: true,
getHtmlTpl: function () {
return '' +
'
' +
this.renderLabelHtml() +
'
' +
'
';
},
postRender: function () {
var me = this;
this.addListener('over', function () {
me.ownerMenu.fireEvent('submenuover', me);
if (me.subMenu) {
me.delayShowSubMenu();
}
});
if (this.subMenu) {
this.getDom().className += ' edui-hassubmenu';
this.subMenu.render();
this.addListener('out', function () {
me.delayHideSubMenu();
});
this.subMenu.addListener('over', function () {
clearTimeout(me._closingTimer);
me._closingTimer = null;
me.addState('opened');
});
this.ownerMenu.addListener('hide', function () {
me.hideSubMenu();
});
this.ownerMenu.addListener('submenuover', function (t, subMenu) {
if (subMenu !== me) {
me.delayHideSubMenu();
}
});
this.subMenu._bakQueryAutoHide = this.subMenu.queryAutoHide;
this.subMenu.queryAutoHide = function (el) {
if (el && uiUtils.contains(me.getDom(), el)) {
return false;
}
return this._bakQueryAutoHide(el);
};
}
this.getDom().style.tabIndex = '-1';
uiUtils.makeUnselectable(this.getDom());
this.Stateful_postRender();
},
delayShowSubMenu: function () {
var me = this;
if (!me.isDisabled()) {
me.addState('opened');
clearTimeout(me._showingTimer);
clearTimeout(me._closingTimer);
me._closingTimer = null;
me._showingTimer = setTimeout(function () {
me.showSubMenu();
}, 250);
}
},
delayHideSubMenu: function () {
var me = this;
if (!me.isDisabled()) {
me.removeState('opened');
clearTimeout(me._showingTimer);
if (!me._closingTimer) {
me._closingTimer = setTimeout(function () {
if (!me.hasState('opened')) {
me.hideSubMenu();
}
me._closingTimer = null;
}, 400);
}
}
},
renderLabelHtml: function () {
return '
' +
'
' +
'' + (this.label || '') + '
';
},
getStateDom: function () {
return this.getDom();
},
queryAutoHide: function (el) {
if (this.subMenu && this.hasState('opened')) {
return this.subMenu.queryAutoHide(el);
}
},
_onClick: function (event, this_) {
if (this.hasState('disabled')) return;
if (this.fireEvent('click', event, this_) !== false) {
if (this.subMenu) {
this.showSubMenu();
} else {
Popup.postHide(event);
}
}
},
showSubMenu: function () {
var rect = uiUtils.getClientRect(this.getDom());
rect.right -= 5;
rect.left += 2;
rect.width -= 7;
rect.top -= 4;
rect.bottom += 4;
rect.height += 8;
this.subMenu.showAnchorRect(rect, true, true);
},
hideSubMenu: function () {
this.subMenu.hide();
}
};
utils.inherits(MenuItem, UIBase);
utils.extend(MenuItem.prototype, Stateful, true);
})();
// ui/combox.js
///import core
///import uicore
///import ui/menu.js
///import ui/splitbutton.js
(function () {
// todo: menu和item提成通用list
var utils = baidu.editor.utils,
uiUtils = baidu.editor.ui.uiUtils,
Menu = baidu.editor.ui.Menu,
SplitButton = baidu.editor.ui.SplitButton,
Combox = baidu.editor.ui.Combox = function (options) {
this.initOptions(options);
this.initCombox();
};
Combox.prototype = {
uiName: 'combox',
onbuttonclick: function () {
this.showPopup();
},
initCombox: function () {
var me = this;
this.items = this.items || [];
for (var i = 0; i < this.items.length; i++) {
var item = this.items[i];
item.uiName = 'listitem';
item.index = i;
item.onclick = function () {
me.selectByIndex(this.index);
};
}
this.popup = new Menu({
items: this.items,
uiName: 'list',
editor: this.editor,
captureWheel: true,
combox: this
});
this.initSplitButton();
},
_SplitButton_postRender: SplitButton.prototype.postRender,
postRender: function () {
this._SplitButton_postRender();
this.setLabel(this.label || '');
this.setValue(this.initValue || '');
},
showPopup: function () {
var rect = uiUtils.getClientRect(this.getDom());
rect.top += 1;
rect.bottom -= 1;
rect.height -= 2;
this.popup.showAnchorRect(rect);
},
getValue: function () {
return this.value;
},
setValue: function (value) {
var index = this.indexByValue(value);
if (index != -1) {
this.selectedIndex = index;
this.setLabel(this.items[index].label);
this.value = this.items[index].value;
} else {
this.selectedIndex = -1;
this.setLabel(this.getLabelForUnknowValue(value));
this.value = value;
}
},
setLabel: function (label) {
this.getDom('button_body').innerHTML = label;
this.label = label;
},
getLabelForUnknowValue: function (value) {
return value;
},
indexByValue: function (value) {
for (var i = 0; i < this.items.length; i++) {
if (value == this.items[i].value) {
return i;
}
}
return -1;
},
getItem: function (index) {
return this.items[index];
},
selectByIndex: function (index) {
if (index < this.items.length && this.fireEvent('select', index) !== false) {
this.selectedIndex = index;
this.value = this.items[index].value;
this.setLabel(this.items[index].label);
}
}
};
utils.inherits(Combox, SplitButton);
})();
// ui/dialog.js
///import core
///import uicore
///import ui/mask.js
///import ui/button.js
(function () {
var utils = baidu.editor.utils,
domUtils = baidu.editor.dom.domUtils,
uiUtils = baidu.editor.ui.uiUtils,
Mask = baidu.editor.ui.Mask,
UIBase = baidu.editor.ui.UIBase,
Button = baidu.editor.ui.Button,
Dialog = baidu.editor.ui.Dialog = function (options) {
if (options.name) {
var name = options.name;
var cssRules = options.cssRules;
if (!options.className) {
options.className = 'edui-for-' + name;
}
if (cssRules) {
options.cssRules = '.edui-default .edui-for-' + name + ' .edui-dialog-content {' + cssRules + '}'
}
}
this.initOptions(utils.extend({
autoReset: true,
draggable: true,
onok: function () { },
oncancel: function () { },
onclose: function (t, ok) {
return ok ? this.onok() : this.oncancel();
},
//是否控制dialog中的scroll事件, 默认为不阻止
holdScroll: false
}, options));
this.initDialog();
};
var modalMask;
var dragMask;
var activeDialog;
Dialog.prototype = {
draggable: false,
uiName: 'dialog',
initDialog: function () {
var me = this,
theme = this.editor.options.theme;
if (this.cssRules) {
utils.cssRule('edui-customize-' + this.name + '-style', this.cssRules);
}
this.initUIBase();
this.modalMask = (modalMask || (modalMask = new Mask({
className: 'edui-dialog-modalmask',
theme: theme,
onclick: function () {
activeDialog && activeDialog.close(false);
}
})));
this.dragMask = (dragMask || (dragMask = new Mask({
className: 'edui-dialog-dragmask',
theme: theme
})));
this.closeButton = new Button({
className: 'edui-dialog-closebutton',
title: me.closeDialog,
theme: theme,
onclick: function () {
me.close(false);
}
});
this.fullscreen && this.initResizeEvent();
if (this.buttons) {
for (var i = 0; i < this.buttons.length; i++) {
if (!(this.buttons[i] instanceof Button)) {
this.buttons[i] = new Button(utils.extend(this.buttons[i], {
editor: this.editor
}, true));
}
}
}
},
initResizeEvent: function () {
var me = this;
domUtils.on(window, "resize", function () {
if (me._hidden || me._hidden === undefined) {
return;
}
if (me.__resizeTimer) {
window.clearTimeout(me.__resizeTimer);
}
me.__resizeTimer = window.setTimeout(function () {
me.__resizeTimer = null;
var dialogWrapNode = me.getDom(),
contentNode = me.getDom('content'),
wrapRect = UE.ui.uiUtils.getClientRect(dialogWrapNode),
contentRect = UE.ui.uiUtils.getClientRect(contentNode),
vpRect = uiUtils.getViewportRect();
contentNode.style.width = (vpRect.width - wrapRect.width + contentRect.width) + "px";
contentNode.style.height = (vpRect.height - wrapRect.height + contentRect.height) + "px";
dialogWrapNode.style.width = vpRect.width + "px";
dialogWrapNode.style.height = vpRect.height + "px";
me.fireEvent("resize");
}, 100);
});
},
fitSize: function () {
var popBodyEl = this.getDom('body');
// if (!(baidu.editor.browser.ie && baidu.editor.browser.version == 7)) {
// uiUtils.removeStyle(popBodyEl, 'width');
// uiUtils.removeStyle(popBodyEl, 'height');
// }
var size = this.mesureSize();
popBodyEl.style.width = size.width + 'px';
popBodyEl.style.height = size.height + 'px';
return size;
},
safeSetOffset: function (offset) {
var me = this;
var el = me.getDom();
var vpRect = uiUtils.getViewportRect();
var rect = uiUtils.getClientRect(el);
var left = offset.left;
if (left + rect.width > vpRect.right) {
left = vpRect.right - rect.width;
}
var top = offset.top;
if (top + rect.height > vpRect.bottom) {
top = vpRect.bottom - rect.height;
}
el.style.left = Math.max(left, 0) + 'px';
el.style.top = Math.max(top, 0) + 'px';
},
showAtCenter: function () {
var vpRect = uiUtils.getViewportRect();
if (!this.fullscreen) {
this.getDom().style.display = '';
var popSize = this.fitSize();
var titleHeight = this.getDom('titlebar').offsetHeight | 0;
var left = vpRect.width / 2 - popSize.width / 2;
var top = vpRect.height / 2 - (popSize.height - titleHeight) / 2 - titleHeight;
var popEl = this.getDom();
this.safeSetOffset({
left: Math.max(left | 0, 0),
top: Math.max(top | 0, 0)
});
if (!domUtils.hasClass(popEl, 'edui-state-centered')) {
popEl.className += ' edui-state-centered';
}
} else {
var dialogWrapNode = this.getDom(),
contentNode = this.getDom('content');
dialogWrapNode.style.display = "block";
var wrapRect = UE.ui.uiUtils.getClientRect(dialogWrapNode),
contentRect = UE.ui.uiUtils.getClientRect(contentNode);
dialogWrapNode.style.left = "-100000px";
contentNode.style.width = (vpRect.width - wrapRect.width + contentRect.width) + "px";
contentNode.style.height = (vpRect.height - wrapRect.height + contentRect.height) + "px";
dialogWrapNode.style.width = vpRect.width + "px";
dialogWrapNode.style.height = vpRect.height + "px";
dialogWrapNode.style.left = 0;
//保存环境的overflow值
this._originalContext = {
html: {
overflowX: document.documentElement.style.overflowX,
overflowY: document.documentElement.style.overflowY
},
body: {
overflowX: document.body.style.overflowX,
overflowY: document.body.style.overflowY
}
};
document.documentElement.style.overflowX = 'hidden';
document.documentElement.style.overflowY = 'hidden';
document.body.style.overflowX = 'hidden';
document.body.style.overflowY = 'hidden';
}
this._show();
},
getContentHtml: function () {
var contentHtml = '';
if (typeof this.content == 'string') {
contentHtml = this.content;
} else if (this.iframeUrl) {
contentHtml = ' ';
}
return contentHtml;
},
getHtmlTpl: function () {
var footHtml = '';
if (this.buttons) {
var buff = [];
for (var i = 0; i < this.buttons.length; i++) {
buff[i] = this.buttons[i].renderHtml();
}
footHtml = '';
}
return '' +
'
' +
'
' +
'
' +
'' + (this.title || '') + ' ' +
'
' +
this.closeButton.renderHtml() +
'
' +
'
' + (this.autoReset ? '' : this.getContentHtml()) + '
' +
footHtml +
'
';
},
postRender: function () {
// todo: 保持居中/记住上次关闭位置选项
if (!this.modalMask.getDom()) {
this.modalMask.render();
this.modalMask.hide();
}
if (!this.dragMask.getDom()) {
this.dragMask.render();
this.dragMask.hide();
}
var me = this;
this.addListener('show', function () {
me.modalMask.show(this.getDom().style.zIndex - 2);
});
this.addListener('hide', function () {
me.modalMask.hide();
});
if (this.buttons) {
for (var i = 0; i < this.buttons.length; i++) {
this.buttons[i].postRender();
}
}
domUtils.on(window, 'resize', function () {
setTimeout(function () {
if (!me.isHidden()) {
me.safeSetOffset(uiUtils.getClientRect(me.getDom()));
}
});
});
//hold住scroll事件,防止dialog的滚动影响页面
// if( this.holdScroll ) {
//
// if( !me.iframeUrl ) {
// domUtils.on( document.getElementById( me.id + "_iframe"), !browser.gecko ? "mousewheel" : "DOMMouseScroll", function(e){
// domUtils.preventDefault(e);
// } );
// } else {
// me.addListener('dialogafterreset', function(){
// window.setTimeout(function(){
// var iframeWindow = document.getElementById( me.id + "_iframe").contentWindow;
//
// if( browser.ie ) {
//
// var timer = window.setInterval(function(){
//
// if( iframeWindow.document && iframeWindow.document.body ) {
// window.clearInterval( timer );
// timer = null;
// domUtils.on( iframeWindow.document.body, !browser.gecko ? "mousewheel" : "DOMMouseScroll", function(e){
// domUtils.preventDefault(e);
// } );
// }
//
// }, 100);
//
// } else {
// domUtils.on( iframeWindow, !browser.gecko ? "mousewheel" : "DOMMouseScroll", function(e){
// domUtils.preventDefault(e);
// } );
// }
//
// }, 1);
// });
// }
//
// }
this._hide();
},
mesureSize: function () {
var body = this.getDom('body');
var width = uiUtils.getClientRect(this.getDom('content')).width;
var dialogBodyStyle = body.style;
dialogBodyStyle.width = width;
return uiUtils.getClientRect(body);
},
_onTitlebarMouseDown: function (evt, el) {
if (this.draggable) {
var rect;
var vpRect = uiUtils.getViewportRect();
var me = this;
uiUtils.startDrag(evt, {
ondragstart: function () {
rect = uiUtils.getClientRect(me.getDom());
me.getDom('contmask').style.visibility = 'visible';
me.dragMask.show(me.getDom().style.zIndex - 1);
},
ondragmove: function (x, y) {
var left = rect.left + x;
var top = rect.top + y;
me.safeSetOffset({
left: left,
top: top
});
},
ondragstop: function () {
me.getDom('contmask').style.visibility = 'hidden';
domUtils.removeClasses(me.getDom(), ['edui-state-centered']);
me.dragMask.hide();
}
});
}
},
reset: function () {
this.getDom('content').innerHTML = this.getContentHtml();
this.fireEvent('dialogafterreset');
},
_show: function () {
if (this._hidden) {
this.getDom().style.display = '';
//要高过编辑器的zindxe
this.editor.container.style.zIndex && (this.getDom().style.zIndex = this.editor.container.style.zIndex * 1 + 10);
this._hidden = false;
this.fireEvent('show');
baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = this.getDom().style.zIndex - 4;
}
},
isHidden: function () {
return this._hidden;
},
_hide: function () {
if (!this._hidden) {
var wrapNode = this.getDom();
wrapNode.style.display = 'none';
wrapNode.style.zIndex = '';
wrapNode.style.width = '';
wrapNode.style.height = '';
this._hidden = true;
this.fireEvent('hide');
}
},
open: function () {
if (this.autoReset) {
//有可能还没有渲染
try {
this.reset();
} catch (e) {
this.render();
this.open()
}
}
this.showAtCenter();
if (this.iframeUrl) {
try {
this.getDom('iframe').focus();
} catch (ex) { }
}
activeDialog = this;
},
_onCloseButtonClick: function (evt, el) {
this.close(false);
},
close: function (ok) {
if (this.fireEvent('close', ok) !== false) {
//还原环境
if (this.fullscreen) {
document.documentElement.style.overflowX = this._originalContext.html.overflowX;
document.documentElement.style.overflowY = this._originalContext.html.overflowY;
document.body.style.overflowX = this._originalContext.body.overflowX;
document.body.style.overflowY = this._originalContext.body.overflowY;
delete this._originalContext;
}
this._hide();
//销毁content
var content = this.getDom('content');
var iframe = this.getDom('iframe');
if (content && iframe) {
var doc = iframe.contentDocument || iframe.contentWindow.document;
doc && (doc.body.innerHTML = '');
domUtils.remove(content);
}
}
}
};
utils.inherits(Dialog, UIBase);
})();
// ui/menubutton.js
///import core
///import uicore
///import ui/menu.js
///import ui/splitbutton.js
(function () {
var utils = baidu.editor.utils,
Menu = baidu.editor.ui.Menu,
SplitButton = baidu.editor.ui.SplitButton,
MenuButton = baidu.editor.ui.MenuButton = function (options) {
this.initOptions(options);
this.initMenuButton();
};
MenuButton.prototype = {
initMenuButton: function () {
var me = this;
this.uiName = "menubutton";
this.popup = new Menu({
items: me.items,
className: me.className,
editor: me.editor
});
this.popup.addListener('show', function () {
var list = this;
for (var i = 0; i < list.items.length; i++) {
list.items[i].removeState('checked');
if (list.items[i].value == me._value) {
list.items[i].addState('checked');
this.value = me._value;
}
}
});
this.initSplitButton();
},
setValue: function (value) {
this._value = value;
}
};
utils.inherits(MenuButton, SplitButton);
})();
// ui/multiMenu.js
///import core
///import uicore
///commands 表情
(function () {
var utils = baidu.editor.utils,
Popup = baidu.editor.ui.Popup,
SplitButton = baidu.editor.ui.SplitButton,
MultiMenuPop = baidu.editor.ui.MultiMenuPop = function (options) {
this.initOptions(options);
this.initMultiMenu();
};
MultiMenuPop.prototype = {
initMultiMenu: function () {
var me = this;
this.popup = new Popup({
content: '',
editor: me.editor,
iframe_rendered: false,
onshow: function () {
if (!this.iframe_rendered) {
this.iframe_rendered = true;
this.getDom('content').innerHTML = '';
me.editor.container.style.zIndex && (this.getDom().style.zIndex = me.editor.container.style.zIndex * 1 + 1);
}
}
// canSideUp:false,
// canSideLeft:false
});
this.onbuttonclick = function () {
this.showPopup();
};
this.initSplitButton();
}
};
utils.inherits(MultiMenuPop, SplitButton);
})();
// ui/shortcutmenu.js
(function () {
var UI = baidu.editor.ui,
UIBase = UI.UIBase,
uiUtils = UI.uiUtils,
utils = baidu.editor.utils,
domUtils = baidu.editor.dom.domUtils;
var allMenus = [],//存储所有快捷菜单
timeID,
isSubMenuShow = false;//是否有子pop显示
var ShortCutMenu = UI.ShortCutMenu = function (options) {
this.initOptions(options);
this.initShortCutMenu();
};
ShortCutMenu.postHide = hideAllMenu;
ShortCutMenu.prototype = {
isHidden: true,
SPACE: 5,
initShortCutMenu: function () {
this.items = this.items || [];
this.initUIBase();
this.initItems();
this.initEvent();
allMenus.push(this);
},
initEvent: function () {
var me = this,
doc = me.editor.document;
domUtils.on(doc, "mousemove", function (e) {
if (me.isHidden === false) {
//有pop显示就不隐藏快捷菜单
if (me.getSubMenuMark() || me.eventType == "contextmenu") return;
var flag = true,
el = me.getDom(),
wt = el.offsetWidth,
ht = el.offsetHeight,
distanceX = wt / 2 + me.SPACE,//距离中心X标准
distanceY = ht / 2,//距离中心Y标准
x = Math.abs(e.screenX - me.left),//离中心距离横坐标
y = Math.abs(e.screenY - me.top);//离中心距离纵坐标
clearTimeout(timeID);
timeID = setTimeout(function () {
if (y > 0 && y < distanceY) {
me.setOpacity(el, "1");
} else if (y > distanceY && y < distanceY + 70) {
me.setOpacity(el, "0.5");
flag = false;
} else if (y > distanceY + 70 && y < distanceY + 140) {
me.hide();
}
if (flag && x > 0 && x < distanceX) {
me.setOpacity(el, "1")
} else if (x > distanceX && x < distanceX + 70) {
me.setOpacity(el, "0.5")
} else if (x > distanceX + 70 && x < distanceX + 140) {
me.hide();
}
});
}
});
//ie\ff下 mouseout不准
if (browser.chrome) {
domUtils.on(doc, "mouseout", function (e) {
var relatedTgt = e.relatedTarget || e.toElement;
if (relatedTgt == null || relatedTgt.tagName == "HTML") {
me.hide();
}
});
}
me.editor.addListener("afterhidepop", function () {
if (!me.isHidden) {
isSubMenuShow = true;
}
});
},
initItems: function () {
if (utils.isArray(this.items)) {
for (var i = 0, len = this.items.length; i < len; i++) {
var item = this.items[i].toLowerCase();
if (UI[item]) {
this.items[i] = new UI[item](this.editor);
this.items[i].className += " edui-shortcutsubmenu ";
}
}
}
},
setOpacity: function (el, value) {
if (browser.ie && browser.version < 9) {
el.style.filter = "alpha(opacity = " + parseFloat(value) * 100 + ");"
} else {
el.style.opacity = value;
}
},
getSubMenuMark: function () {
isSubMenuShow = false;
var layerEle = uiUtils.getFixedLayer();
var list = domUtils.getElementsByTagName(layerEle, "div", function (node) {
return domUtils.hasClass(node, "edui-shortcutsubmenu edui-popup")
});
for (var i = 0, node; node = list[i++];) {
if (node.style.display != "none") {
isSubMenuShow = true;
}
}
return isSubMenuShow;
},
show: function (e, hasContextmenu) {
var me = this,
offset = {},
el = this.getDom(),
fixedlayer = uiUtils.getFixedLayer();
function setPos(offset) {
if (offset.left < 0) {
offset.left = 0;
}
if (offset.top < 0) {
offset.top = 0;
}
el.style.cssText = "position:absolute;left:" + offset.left + "px;top:" + offset.top + "px;";
}
function setPosByCxtMenu(menu) {
if (!menu.tagName) {
menu = menu.getDom();
}
offset.left = parseInt(menu.style.left);
offset.top = parseInt(menu.style.top);
offset.top -= el.offsetHeight + 15;
setPos(offset);
}
me.eventType = e.type;
el.style.cssText = "display:block;left:-9999px";
if (e.type == "contextmenu" && hasContextmenu) {
var menu = domUtils.getElementsByTagName(fixedlayer, "div", "edui-contextmenu")[0];
if (menu) {
setPosByCxtMenu(menu)
} else {
me.editor.addListener("aftershowcontextmenu", function (type, menu) {
setPosByCxtMenu(menu);
});
}
} else {
offset = uiUtils.getViewportOffsetByEvent(e);
offset.top -= el.offsetHeight + me.SPACE;
offset.left += me.SPACE + 20;
setPos(offset);
me.setOpacity(el, 0.2);
}
me.isHidden = false;
me.left = e.screenX + el.offsetWidth / 2 - me.SPACE;
me.top = e.screenY - (el.offsetHeight / 2) - me.SPACE;
if (me.editor) {
el.style.zIndex = me.editor.container.style.zIndex * 1 + 10;
fixedlayer.style.zIndex = el.style.zIndex - 1;
}
},
hide: function () {
if (this.getDom()) {
this.getDom().style.display = "none";
}
this.isHidden = true;
},
postRender: function () {
if (utils.isArray(this.items)) {
for (var i = 0, item; item = this.items[i++];) {
item.postRender();
}
}
},
getHtmlTpl: function () {
var buff;
if (utils.isArray(this.items)) {
buff = [];
for (var i = 0; i < this.items.length; i++) {
buff[i] = this.items[i].renderHtml();
}
buff = buff.join("");
} else {
buff = this.items;
}
return '' +
buff +
'
';
}
};
utils.inherits(ShortCutMenu, UIBase);
function hideAllMenu(e) {
var tgt = e.target || e.srcElement,
cur = domUtils.findParent(tgt, function (node) {
return domUtils.hasClass(node, "edui-shortcutmenu") || domUtils.hasClass(node, "edui-popup");
}, true);
if (!cur) {
for (var i = 0, menu; menu = allMenus[i++];) {
menu.hide()
}
}
}
domUtils.on(document, 'mousedown', function (e) {
hideAllMenu(e);
});
domUtils.on(window, 'scroll', function (e) {
hideAllMenu(e);
});
})();
// ui/breakline.js
(function () {
var utils = baidu.editor.utils,
UIBase = baidu.editor.ui.UIBase,
Breakline = baidu.editor.ui.Breakline = function (options) {
this.initOptions(options);
this.initSeparator();
};
Breakline.prototype = {
uiName: 'Breakline',
initSeparator: function () {
this.initUIBase();
},
getHtmlTpl: function () {
return ' ';
}
};
utils.inherits(Breakline, UIBase);
})();
// ui/message.js
///import core
///import uicore
(function () {
var utils = baidu.editor.utils,
domUtils = baidu.editor.dom.domUtils,
UIBase = baidu.editor.ui.UIBase,
Message = baidu.editor.ui.Message = function (options) {
this.initOptions(options);
this.initMessage();
};
Message.prototype = {
initMessage: function () {
this.initUIBase();
},
getHtmlTpl: function () {
return '' +
'
×
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
';
},
reset: function (opt) {
var me = this;
if (!opt.keepshow) {
clearTimeout(this.timer);
me.timer = setTimeout(function () {
me.hide();
}, opt.timeout || 4000);
}
opt.content !== undefined && me.setContent(opt.content);
opt.type !== undefined && me.setType(opt.type);
me.show();
},
postRender: function () {
var me = this,
closer = this.getDom('closer');
closer && domUtils.on(closer, 'click', function () {
me.hide();
});
},
setContent: function (content) {
this.getDom('content').innerHTML = content;
},
setType: function (type) {
type = type || 'info';
var body = this.getDom('body');
body.className = body.className.replace(/edui-message-type-[\w-]+/, 'edui-message-type-' + type);
},
getContent: function () {
return this.getDom('content').innerHTML;
},
getType: function () {
var arr = this.getDom('body').match(/edui-message-type-([\w-]+)/);
return arr ? arr[1] : '';
},
show: function () {
this.getDom().style.display = 'block';
},
hide: function () {
var dom = this.getDom();
if (dom) {
dom.style.display = 'none';
dom.parentNode && dom.parentNode.removeChild(dom);
}
}
};
utils.inherits(Message, UIBase);
})();
// adapter/editorui.js
//ui跟编辑器的适配層
//那个按钮弹出是dialog,是下拉筐等都是在这个js中配置
//自己写的ui也要在这里配置,放到baidu.editor.ui下边,当编辑器实例化的时候会根据ueditor.config中的toolbars找到相应的进行实例化
(function () {
var utils = baidu.editor.utils;
var editorui = baidu.editor.ui;
var _Dialog = editorui.Dialog;
editorui.buttons = {};
editorui.Dialog = function (options) {
var dialog = new _Dialog(options);
dialog.addListener('hide', function () {
if (dialog.editor) {
var editor = dialog.editor;
try {
if (browser.gecko) {
var y = editor.window.scrollY,
x = editor.window.scrollX;
editor.body.focus();
editor.window.scrollTo(x, y);
} else {
editor.focus();
}
} catch (ex) {
}
}
});
return dialog;
};
var iframeUrlMap = {
'anchor': '~/dialogs/anchor/anchor.html',
'insertimage': '~/dialogs/image/image.html',
'link': '~/dialogs/link/link.html',
'spechars': '~/dialogs/spechars/spechars.html',
'searchreplace': '~/dialogs/searchreplace/searchreplace.html',
'map': '~/dialogs/map/map.html',
'gmap': '~/dialogs/gmap/gmap.html',
'insertvideo': '~/dialogs/video/video.html',
'help': '~/dialogs/help/help.html',
'preview': '~/dialogs/preview/preview.html',
'emotion': '~/dialogs/emotion/emotion.html',
'wordimage': '~/dialogs/wordimage/wordimage.html',
'attachment': '~/dialogs/attachment/attachment.html',
'insertframe': '~/dialogs/insertframe/insertframe.html',
'edittip': '~/dialogs/table/edittip.html',
'edittable': '~/dialogs/table/edittable.html',
'edittd': '~/dialogs/table/edittd.html',
'webapp': '~/dialogs/webapp/webapp.html',
'snapscreen': '~/dialogs/snapscreen/snapscreen.html',
'scrawl': '~/dialogs/scrawl/scrawl.html',
'music': '~/dialogs/music/music.html',
'template': '~/dialogs/template/template.html',
'background': '~/dialogs/background/background.html',
'charts': '~/dialogs/charts/charts.html'
};
//为工具栏添加按钮,以下都是统一的按钮触发命令,所以写在一起
var btnCmds = ['undo', 'redo', 'formatmatch',
'bold', 'italic', 'underline', 'fontborder', 'touppercase', 'tolowercase',
'strikethrough', 'subscript', 'superscript', 'source', 'indent', 'outdent',
'blockquote', 'pasteplain', 'pagebreak',
'selectall', 'print', 'horizontal', 'removeformat', 'time', 'date', 'unlink',
'insertparagraphbeforetable', 'insertrow', 'insertcol', 'mergeright', 'mergedown', 'deleterow',
'deletecol', 'splittorows', 'splittocols', 'splittocells', 'mergecells', 'deletetable', 'drafts'];
for (var i = 0, ci; ci = btnCmds[i++];) {
ci = ci.toLowerCase();
editorui[ci] = function (cmd) {
return function (editor) {
var ui = new editorui.Button({
className: 'edui-for-' + cmd,
title: editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd) || '',
onclick: function () {
editor.execCommand(cmd);
},
theme: editor.options.theme,
showText: false
});
editorui.buttons[cmd] = ui;
editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
var state = editor.queryCommandState(cmd);
if (state == -1) {
ui.setDisabled(true);
ui.setChecked(false);
} else {
if (!uiReady) {
ui.setDisabled(false);
ui.setChecked(state);
}
}
});
return ui;
};
}(ci);
}
//清除文档
editorui.cleardoc = function (editor) {
var ui = new editorui.Button({
className: 'edui-for-cleardoc',
title: editor.options.labelMap.cleardoc || editor.getLang("labelMap.cleardoc") || '',
theme: editor.options.theme,
onclick: function () {
if (confirm(editor.getLang("confirmClear"))) {
editor.execCommand('cleardoc');
}
}
});
editorui.buttons["cleardoc"] = ui;
editor.addListener('selectionchange', function () {
ui.setDisabled(editor.queryCommandState('cleardoc') == -1);
});
return ui;
};
//排版,图片排版,文字方向
var typeset = {
'justify': ['left', 'right', 'center', 'justify'],
'imagefloat': ['none', 'left', 'center', 'right'],
'directionality': ['ltr', 'rtl']
};
for (var p in typeset) {
(function (cmd, val) {
for (var i = 0, ci; ci = val[i++];) {
(function (cmd2) {
editorui[cmd.replace('float', '') + cmd2] = function (editor) {
var ui = new editorui.Button({
className: 'edui-for-' + cmd.replace('float', '') + cmd2,
title: editor.options.labelMap[cmd.replace('float', '') + cmd2] || editor.getLang("labelMap." + cmd.replace('float', '') + cmd2) || '',
theme: editor.options.theme,
onclick: function () {
editor.execCommand(cmd, cmd2);
}
});
editorui.buttons[cmd] = ui;
editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
ui.setDisabled(editor.queryCommandState(cmd) == -1);
ui.setChecked(editor.queryCommandValue(cmd) == cmd2 && !uiReady);
});
return ui;
};
})(ci)
}
})(p, typeset[p])
}
//字体颜色和背景颜色
for (var i = 0, ci; ci = ['backcolor', 'forecolor'][i++];) {
editorui[ci] = function (cmd) {
return function (editor) {
var ui = new editorui.ColorButton({
className: 'edui-for-' + cmd,
color: 'default',
title: editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd) || '',
editor: editor,
onpickcolor: function (t, color) {
editor.execCommand(cmd, color);
},
onpicknocolor: function () {
editor.execCommand(cmd, 'default');
this.setColor('transparent');
this.color = 'default';
},
onbuttonclick: function () {
editor.execCommand(cmd, this.color);
}
});
editorui.buttons[cmd] = ui;
editor.addListener('selectionchange', function () {
ui.setDisabled(editor.queryCommandState(cmd) == -1);
});
return ui;
};
}(ci);
}
var dialogBtns = {
noOk: ['searchreplace', 'help', 'spechars', 'webapp', 'preview'],
ok: ['attachment', 'anchor', 'link', 'insertimage', 'map', 'gmap', 'insertframe', 'wordimage',
'insertvideo', 'insertframe', 'edittip', 'edittable', 'edittd', 'scrawl', 'template', 'music', 'background', 'charts']
};
for (var p in dialogBtns) {
(function (type, vals) {
for (var i = 0, ci; ci = vals[i++];) {
//todo opera下存在问题
if (browser.opera && ci === "searchreplace") {
continue;
}
(function (cmd) {
editorui[cmd] = function (editor, iframeUrl, title) {
iframeUrl = iframeUrl || (editor.options.iframeUrlMap || {})[cmd] || iframeUrlMap[cmd];
title = editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd) || '';
var dialog;
//没有iframeUrl不创建dialog
if (iframeUrl) {
dialog = new editorui.Dialog(utils.extend({
iframeUrl: editor.ui.mapUrl(iframeUrl),
editor: editor,
className: 'edui-for-' + cmd,
title: title,
holdScroll: cmd === 'insertimage',
fullscreen: /charts|preview/.test(cmd),
closeDialog: editor.getLang("closeDialog")
}, type == 'ok' ? {
buttons: [
{
className: 'edui-okbutton',
label: editor.getLang("ok"),
editor: editor,
onclick: function () {
dialog.close(true);
}
},
{
className: 'edui-cancelbutton',
label: editor.getLang("cancel"),
editor: editor,
onclick: function () {
dialog.close(false);
}
}
]
} : {}));
editor.ui._dialogs[cmd + "Dialog"] = dialog;
}
var ui = new editorui.Button({
className: 'edui-for-' + cmd,
title: title,
onclick: function () {
if (dialog) {
switch (cmd) {
case "wordimage":
var images = editor.execCommand("wordimage");
if (images && images.length) {
dialog.render();
dialog.open();
}
break;
case "scrawl":
if (editor.queryCommandState("scrawl") != -1) {
dialog.render();
dialog.open();
}
break;
default:
dialog.render();
dialog.open();
}
}
},
theme: editor.options.theme,
disabled: (cmd == 'scrawl' && editor.queryCommandState("scrawl") == -1) || (cmd == 'charts')
});
editorui.buttons[cmd] = ui;
editor.addListener('selectionchange', function () {
//只存在于右键菜单而无工具栏按钮的ui不需要检测状态
var unNeedCheckState = { 'edittable': 1 };
if (cmd in unNeedCheckState) return;
var state = editor.queryCommandState(cmd);
if (ui.getDom()) {
ui.setDisabled(state == -1);
ui.setChecked(state);
}
});
return ui;
};
})(ci.toLowerCase())
}
})(p, dialogBtns[p]);
}
editorui.snapscreen = function (editor, iframeUrl, title) {
title = editor.options.labelMap['snapscreen'] || editor.getLang("labelMap.snapscreen") || '';
var ui = new editorui.Button({
className: 'edui-for-snapscreen',
title: title,
onclick: function () {
editor.execCommand("snapscreen");
},
theme: editor.options.theme
});
editorui.buttons['snapscreen'] = ui;
iframeUrl = iframeUrl || (editor.options.iframeUrlMap || {})["snapscreen"] || iframeUrlMap["snapscreen"];
if (iframeUrl) {
var dialog = new editorui.Dialog({
iframeUrl: editor.ui.mapUrl(iframeUrl),
editor: editor,
className: 'edui-for-snapscreen',
title: title,
buttons: [
{
className: 'edui-okbutton',
label: editor.getLang("ok"),
editor: editor,
onclick: function () {
dialog.close(true);
}
},
{
className: 'edui-cancelbutton',
label: editor.getLang("cancel"),
editor: editor,
onclick: function () {
dialog.close(false);
}
}
]
});
dialog.render();
editor.ui._dialogs["snapscreenDialog"] = dialog;
}
editor.addListener('selectionchange', function () {
ui.setDisabled(editor.queryCommandState('snapscreen') == -1);
});
return ui;
};
editorui.insertcode = function (editor, list, title) {
list = editor.options['insertcode'] || [];
title = editor.options.labelMap['insertcode'] || editor.getLang("labelMap.insertcode") || '';
// if (!list.length) return;
var items = [];
utils.each(list, function (key, val) {
items.push({
label: key,
value: val,
theme: editor.options.theme,
renderLabelHtml: function () {
return '' + (this.label || '') + '
';
}
});
});
var ui = new editorui.Combox({
editor: editor,
items: items,
onselect: function (t, index) {
editor.execCommand('insertcode', this.items[index].value);
},
onbuttonclick: function () {
this.showPopup();
},
title: title,
initValue: title,
className: 'edui-for-insertcode',
indexByValue: function (value) {
if (value) {
for (var i = 0, ci; ci = this.items[i]; i++) {
if (ci.value.indexOf(value) != -1)
return i;
}
}
return -1;
}
});
editorui.buttons['insertcode'] = ui;
editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
if (!uiReady) {
var state = editor.queryCommandState('insertcode');
if (state == -1) {
ui.setDisabled(true);
} else {
ui.setDisabled(false);
var value = editor.queryCommandValue('insertcode');
if (!value) {
ui.setValue(title);
return;
}
//trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号
value && (value = value.replace(/['"]/g, '').split(',')[0]);
ui.setValue(value);
}
}
});
return ui;
};
editorui.fontfamily = function (editor, list, title) {
list = editor.options['fontfamily'] || [];
title = editor.options.labelMap['fontfamily'] || editor.getLang("labelMap.fontfamily") || '';
if (!list.length) return;
for (var i = 0, ci, items = []; ci = list[i]; i++) {
var langLabel = editor.getLang('fontfamily')[ci.name] || "";
(function (key, val) {
items.push({
label: key,
value: val,
theme: editor.options.theme,
renderLabelHtml: function () {
return '' + (this.label || '') + '
';
}
});
})(ci.label || langLabel, ci.val)
}
var ui = new editorui.Combox({
editor: editor,
items: items,
onselect: function (t, index) {
editor.execCommand('FontFamily', this.items[index].value);
},
onbuttonclick: function () {
this.showPopup();
},
title: title,
initValue: title,
className: 'edui-for-fontfamily',
indexByValue: function (value) {
if (value) {
for (var i = 0, ci; ci = this.items[i]; i++) {
if (ci.value.indexOf(value) != -1)
return i;
}
}
return -1;
}
});
editorui.buttons['fontfamily'] = ui;
editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
if (!uiReady) {
var state = editor.queryCommandState('FontFamily');
if (state == -1) {
ui.setDisabled(true);
} else {
ui.setDisabled(false);
var value = editor.queryCommandValue('FontFamily');
//trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号
value && (value = value.replace(/['"]/g, '').split(',')[0]);
ui.setValue(value);
}
}
});
return ui;
};
editorui.fontsize = function (editor, list, title) {
title = editor.options.labelMap['fontsize'] || editor.getLang("labelMap.fontsize") || '';
list = list || editor.options['fontsize'] || [];
if (!list.length) return;
var items = [];
for (var i = 0; i < list.length; i++) {
var size = list[i] + 'px';
items.push({
label: size,
value: size,
theme: editor.options.theme,
renderLabelHtml: function () {
return '' + (this.label || '') + '
';
}
});
}
var ui = new editorui.Combox({
editor: editor,
items: items,
title: title,
initValue: title,
onselect: function (t, index) {
editor.execCommand('FontSize', this.items[index].value);
},
onbuttonclick: function () {
this.showPopup();
},
className: 'edui-for-fontsize'
});
editorui.buttons['fontsize'] = ui;
editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
if (!uiReady) {
var state = editor.queryCommandState('FontSize');
if (state == -1) {
ui.setDisabled(true);
} else {
ui.setDisabled(false);
ui.setValue(editor.queryCommandValue('FontSize'));
}
}
});
return ui;
};
editorui.paragraph = function (editor, list, title) {
title = editor.options.labelMap['paragraph'] || editor.getLang("labelMap.paragraph") || '';
list = editor.options['paragraph'] || [];
if (utils.isEmptyObject(list)) return;
var items = [];
for (var i in list) {
items.push({
value: i,
label: list[i] || editor.getLang("paragraph")[i],
theme: editor.options.theme,
renderLabelHtml: function () {
return '' + (this.label || '') + '
';
}
})
}
var ui = new editorui.Combox({
editor: editor,
items: items,
title: title,
initValue: title,
className: 'edui-for-paragraph',
onselect: function (t, index) {
editor.execCommand('Paragraph', this.items[index].value);
},
onbuttonclick: function () {
this.showPopup();
}
});
editorui.buttons['paragraph'] = ui;
editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
if (!uiReady) {
var state = editor.queryCommandState('Paragraph');
if (state == -1) {
ui.setDisabled(true);
} else {
ui.setDisabled(false);
var value = editor.queryCommandValue('Paragraph');
var index = ui.indexByValue(value);
if (index != -1) {
ui.setValue(value);
} else {
ui.setValue(ui.initValue);
}
}
}
});
return ui;
};
//自定义标题
editorui.customstyle = function (editor) {
var list = editor.options['customstyle'] || [],
title = editor.options.labelMap['customstyle'] || editor.getLang("labelMap.customstyle") || '';
if (!list.length) return;
var langCs = editor.getLang('customstyle');
for (var i = 0, items = [], t; t = list[i++];) {
(function (t) {
var ck = {};
ck.label = t.label ? t.label : langCs[t.name];
ck.style = t.style;
ck.className = t.className;
ck.tag = t.tag;
items.push({
label: ck.label,
value: ck,
theme: editor.options.theme,
renderLabelHtml: function () {
return '' + '<' + ck.tag + ' ' + (ck.className ? ' class="' + ck.className + '"' : "")
+ (ck.style ? ' style="' + ck.style + '"' : "") + '>' + ck.label + "<\/" + ck.tag + ">"
+ '
';
}
});
})(t);
}
var ui = new editorui.Combox({
editor: editor,
items: items,
title: title,
initValue: title,
className: 'edui-for-customstyle',
onselect: function (t, index) {
editor.execCommand('customstyle', this.items[index].value);
},
onbuttonclick: function () {
this.showPopup();
},
indexByValue: function (value) {
for (var i = 0, ti; ti = this.items[i++];) {
if (ti.label == value) {
return i - 1
}
}
return -1;
}
});
editorui.buttons['customstyle'] = ui;
editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
if (!uiReady) {
var state = editor.queryCommandState('customstyle');
if (state == -1) {
ui.setDisabled(true);
} else {
ui.setDisabled(false);
var value = editor.queryCommandValue('customstyle');
var index = ui.indexByValue(value);
if (index != -1) {
ui.setValue(value);
} else {
ui.setValue(ui.initValue);
}
}
}
});
return ui;
};
editorui.inserttable = function (editor, iframeUrl, title) {
title = editor.options.labelMap['inserttable'] || editor.getLang("labelMap.inserttable") || '';
var ui = new editorui.TableButton({
editor: editor,
title: title,
className: 'edui-for-inserttable',
onpicktable: function (t, numCols, numRows) {
editor.execCommand('InsertTable', { numRows: numRows, numCols: numCols, border: 1 });
},
onbuttonclick: function () {
this.showPopup();
}
});
editorui.buttons['inserttable'] = ui;
editor.addListener('selectionchange', function () {
ui.setDisabled(editor.queryCommandState('inserttable') == -1);
});
return ui;
};
editorui.lineheight = function (editor) {
var val = editor.options.lineheight || [];
if (!val.length) return;
for (var i = 0, ci, items = []; ci = val[i++];) {
items.push({
//todo:写死了
label: ci,
value: ci,
theme: editor.options.theme,
onclick: function () {
editor.execCommand("lineheight", this.value);
}
})
}
var ui = new editorui.MenuButton({
editor: editor,
className: 'edui-for-lineheight',
title: editor.options.labelMap['lineheight'] || editor.getLang("labelMap.lineheight") || '',
items: items,
onbuttonclick: function () {
var value = editor.queryCommandValue('LineHeight') || this.value;
editor.execCommand("LineHeight", value);
}
});
editorui.buttons['lineheight'] = ui;
editor.addListener('selectionchange', function () {
var state = editor.queryCommandState('LineHeight');
if (state == -1) {
ui.setDisabled(true);
} else {
ui.setDisabled(false);
var value = editor.queryCommandValue('LineHeight');
value && ui.setValue((value + '').replace(/cm/, ''));
ui.setChecked(state)
}
});
return ui;
};
var rowspacings = ['top', 'bottom'];
for (var r = 0, ri; ri = rowspacings[r++];) {
(function (cmd) {
editorui['rowspacing' + cmd] = function (editor) {
var val = editor.options['rowspacing' + cmd] || [];
if (!val.length) return null;
for (var i = 0, ci, items = []; ci = val[i++];) {
items.push({
label: ci,
value: ci,
theme: editor.options.theme,
onclick: function () {
editor.execCommand("rowspacing", this.value, cmd);
}
})
}
var ui = new editorui.MenuButton({
editor: editor,
className: 'edui-for-rowspacing' + cmd,
title: editor.options.labelMap['rowspacing' + cmd] || editor.getLang("labelMap.rowspacing" + cmd) || '',
items: items,
onbuttonclick: function () {
var value = editor.queryCommandValue('rowspacing', cmd) || this.value;
editor.execCommand("rowspacing", value, cmd);
}
});
editorui.buttons[cmd] = ui;
editor.addListener('selectionchange', function () {
var state = editor.queryCommandState('rowspacing', cmd);
if (state == -1) {
ui.setDisabled(true);
} else {
ui.setDisabled(false);
var value = editor.queryCommandValue('rowspacing', cmd);
value && ui.setValue((value + '').replace(/%/, ''));
ui.setChecked(state)
}
});
return ui;
}
})(ri)
}
//有序,无序列表
var lists = ['insertorderedlist', 'insertunorderedlist'];
for (var l = 0, cl; cl = lists[l++];) {
(function (cmd) {
editorui[cmd] = function (editor) {
var vals = editor.options[cmd],
_onMenuClick = function () {
editor.execCommand(cmd, this.value);
}, items = [];
for (var i in vals) {
items.push({
label: vals[i] || editor.getLang()[cmd][i] || "",
value: i,
theme: editor.options.theme,
onclick: _onMenuClick
})
}
var ui = new editorui.MenuButton({
editor: editor,
className: 'edui-for-' + cmd,
title: editor.getLang("labelMap." + cmd) || '',
'items': items,
onbuttonclick: function () {
var value = editor.queryCommandValue(cmd) || this.value;
editor.execCommand(cmd, value);
}
});
editorui.buttons[cmd] = ui;
editor.addListener('selectionchange', function () {
var state = editor.queryCommandState(cmd);
if (state == -1) {
ui.setDisabled(true);
} else {
ui.setDisabled(false);
var value = editor.queryCommandValue(cmd);
ui.setValue(value);
ui.setChecked(state)
}
});
return ui;
};
})(cl)
}
editorui.fullscreen = function (editor, title) {
title = editor.options.labelMap['fullscreen'] || editor.getLang("labelMap.fullscreen") || '';
var ui = new editorui.Button({
className: 'edui-for-fullscreen',
title: title,
theme: editor.options.theme,
onclick: function () {
if (editor.ui) {
editor.ui.setFullScreen(!editor.ui.isFullScreen());
}
this.setChecked(editor.ui.isFullScreen());
}
});
editorui.buttons['fullscreen'] = ui;
editor.addListener('selectionchange', function () {
var state = editor.queryCommandState('fullscreen');
ui.setDisabled(state == -1);
ui.setChecked(editor.ui.isFullScreen());
});
return ui;
};
// 表情
editorui["emotion"] = function (editor, iframeUrl) {
var cmd = "emotion";
var ui = new editorui.MultiMenuPop({
title: editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd + "") || '',
editor: editor,
className: 'edui-for-' + cmd,
iframeUrl: editor.ui.mapUrl(iframeUrl || (editor.options.iframeUrlMap || {})[cmd] || iframeUrlMap[cmd])
});
editorui.buttons[cmd] = ui;
editor.addListener('selectionchange', function () {
ui.setDisabled(editor.queryCommandState(cmd) == -1)
});
return ui;
};
editorui.autotypeset = function (editor) {
var ui = new editorui.AutoTypeSetButton({
editor: editor,
title: editor.options.labelMap['autotypeset'] || editor.getLang("labelMap.autotypeset") || '',
className: 'edui-for-autotypeset',
onbuttonclick: function () {
editor.execCommand('autotypeset')
}
});
editorui.buttons['autotypeset'] = ui;
editor.addListener('selectionchange', function () {
ui.setDisabled(editor.queryCommandState('autotypeset') == -1);
});
return ui;
};
/* 简单上传插件 */
editorui["simpleupload"] = function (editor) {
var name = 'simpleupload',
ui = new editorui.Button({
className: 'edui-for-' + name,
title: editor.options.labelMap[name] || editor.getLang("labelMap." + name) || '',
onclick: function () { },
theme: editor.options.theme,
showText: false
});
editorui.buttons[name] = ui;
editor.addListener('ready', function () {
var b = ui.getDom('body'),
iconSpan = b.children[0];
editor.fireEvent('simpleuploadbtnready', iconSpan);
});
editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
var state = editor.queryCommandState(name);
if (state == -1) {
ui.setDisabled(true);
ui.setChecked(false);
} else {
if (!uiReady) {
ui.setDisabled(false);
ui.setChecked(state);
}
}
});
return ui;
};
})();
// adapter/editor.js
///import core
///commands 全屏
///commandsName FullScreen
///commandsTitle 全屏
(function () {
var utils = baidu.editor.utils,
uiUtils = baidu.editor.ui.uiUtils,
UIBase = baidu.editor.ui.UIBase,
domUtils = baidu.editor.dom.domUtils;
var nodeStack = [];
function EditorUI(options) {
this.initOptions(options);
this.initEditorUI();
}
EditorUI.prototype = {
uiName: 'editor',
initEditorUI: function () {
this.editor.ui = this;
this._dialogs = {};
this.initUIBase();
this._initToolbars();
var editor = this.editor,
me = this;
editor.addListener('ready', function () {
//提供getDialog方法
editor.getDialog = function (name) {
return editor.ui._dialogs[name + "Dialog"];
};
domUtils.on(editor.window, 'scroll', function (evt) {
baidu.editor.ui.Popup.postHide(evt);
});
//提供编辑器实时宽高(全屏时宽高不变化)
editor.ui._actualFrameWidth = editor.options.initialFrameWidth;
UE.browser.ie && UE.browser.version === 6 && editor.container.ownerDocument.execCommand("BackgroundImageCache", false, true);
//display bottom-bar label based on config
if (editor.options.elementPathEnabled) {
editor.ui.getDom('elementpath').innerHTML = '' + editor.getLang("elementPathTip") + ':
';
}
if (editor.options.wordCount) {
function countFn() {
setCount(editor, me);
domUtils.un(editor.document, "click", arguments.callee);
}
domUtils.on(editor.document, "click", countFn);
editor.ui.getDom('wordcount').innerHTML = editor.getLang("wordCountTip");
}
editor.ui._scale();
if (editor.options.scaleEnabled) {
if (editor.autoHeightEnabled) {
editor.disableAutoHeight();
}
me.enableScale();
} else {
me.disableScale();
}
if (!editor.options.elementPathEnabled && !editor.options.wordCount && !editor.options.scaleEnabled) {
editor.ui.getDom('elementpath').style.display = "none";
editor.ui.getDom('wordcount').style.display = "none";
editor.ui.getDom('scale').style.display = "none";
}
if (!editor.selection.isFocus()) return;
editor.fireEvent('selectionchange', false, true);
});
editor.addListener('mousedown', function (t, evt) {
var el = evt.target || evt.srcElement;
baidu.editor.ui.Popup.postHide(evt, el);
baidu.editor.ui.ShortCutMenu.postHide(evt);
});
editor.addListener("delcells", function () {
if (UE.ui['edittip']) {
new UE.ui['edittip'](editor);
}
editor.getDialog('edittip').open();
});
var pastePop, isPaste = false, timer;
editor.addListener("afterpaste", function () {
if (editor.queryCommandState('pasteplain'))
return;
if (baidu.editor.ui.PastePicker) {
pastePop = new baidu.editor.ui.Popup({
content: new baidu.editor.ui.PastePicker({ editor: editor }),
editor: editor,
className: 'edui-wordpastepop'
});
pastePop.render();
}
isPaste = true;
});
editor.addListener("afterinserthtml", function () {
clearTimeout(timer);
timer = setTimeout(function () {
if (pastePop && (isPaste || editor.ui._isTransfer)) {
if (pastePop.isHidden()) {
var span = domUtils.createElement(editor.document, 'span', {
'style': "line-height:0px;",
'innerHTML': '\ufeff'
}),
range = editor.selection.getRange();
range.insertNode(span);
var tmp = getDomNode(span, 'firstChild', 'previousSibling');
tmp && pastePop.showAnchor(tmp.nodeType == 3 ? tmp.parentNode : tmp);
domUtils.remove(span);
} else {
pastePop.show();
}
delete editor.ui._isTransfer;
isPaste = false;
}
}, 200)
});
editor.addListener('contextmenu', function (t, evt) {
baidu.editor.ui.Popup.postHide(evt);
});
editor.addListener('keydown', function (t, evt) {
if (pastePop) pastePop.dispose(evt);
var keyCode = evt.keyCode || evt.which;
if (evt.altKey && keyCode == 90) {
UE.ui.buttons['fullscreen'].onclick();
}
});
editor.addListener('wordcount', function (type) {
setCount(this, me);
});
function setCount(editor, ui) {
editor.setOpt({
wordCount: true,
maximumWords: 10000,
wordCountMsg: editor.options.wordCountMsg || editor.getLang("wordCountMsg"),
wordOverFlowMsg: editor.options.wordOverFlowMsg || editor.getLang("wordOverFlowMsg")
});
var opt = editor.options,
max = opt.maximumWords,
msg = opt.wordCountMsg,
errMsg = opt.wordOverFlowMsg,
countDom = ui.getDom('wordcount');
if (!opt.wordCount) {
return;
}
var count = editor.getContentLength(true);
if (count > max) {
countDom.innerHTML = errMsg;
editor.fireEvent("wordcountoverflow");
} else {
countDom.innerHTML = msg.replace("{#leave}", max - count).replace("{#count}", count);
}
}
editor.addListener('selectionchange', function () {
if (editor.options.elementPathEnabled) {
me[(editor.queryCommandState('elementpath') == -1 ? 'dis' : 'en') + 'ableElementPath']()
}
if (editor.options.scaleEnabled) {
me[(editor.queryCommandState('scale') == -1 ? 'dis' : 'en') + 'ableScale']();
}
});
var popup = new baidu.editor.ui.Popup({
editor: editor,
content: '',
className: 'edui-bubble',
_onEditButtonClick: function () {
this.hide();
editor.ui._dialogs.linkDialog.open();
},
_onImgEditButtonClick: function (name) {
this.hide();
editor.ui._dialogs[name] && editor.ui._dialogs[name].open();
},
_onImgSetFloat: function (value) {
this.hide();
editor.execCommand("imagefloat", value);
},
_setIframeAlign: function (value) {
var frame = popup.anchorEl;
var newFrame = frame.cloneNode(true);
switch (value) {
case -2:
newFrame.setAttribute("align", "");
break;
case -1:
newFrame.setAttribute("align", "left");
break;
case 1:
newFrame.setAttribute("align", "right");
break;
}
frame.parentNode.insertBefore(newFrame, frame);
domUtils.remove(frame);
popup.anchorEl = newFrame;
popup.showAnchor(popup.anchorEl);
},
_updateIframe: function () {
var frame = editor._iframe = popup.anchorEl;
if (domUtils.hasClass(frame, 'ueditor_baidumap')) {
editor.selection.getRange().selectNode(frame).select();
editor.ui._dialogs.mapDialog.open();
popup.hide();
} else {
editor.ui._dialogs.insertframeDialog.open();
popup.hide();
}
},
_onRemoveButtonClick: function (cmdName) {
editor.execCommand(cmdName);
this.hide();
},
queryAutoHide: function (el) {
if (el && el.ownerDocument == editor.document) {
if (el.tagName.toLowerCase() == 'img' || domUtils.findParentByTagName(el, 'a', true)) {
return el !== popup.anchorEl;
}
}
return baidu.editor.ui.Popup.prototype.queryAutoHide.call(this, el);
}
});
popup.render();
if (editor.options.imagePopup) {
editor.addListener('mouseover', function (t, evt) {
evt = evt || window.event;
var el = evt.target || evt.srcElement;
if (editor.ui._dialogs.insertframeDialog && /iframe/ig.test(el.tagName)) {
var html = popup.formatHtml(
'' + editor.getLang("property") + ': ' + editor.getLang("default") + ' ' + editor.getLang("justifyleft") + ' ' + editor.getLang("justifyright") + ' ' +
' ' + editor.getLang("modify") + ' ');
if (html) {
popup.getDom('content').innerHTML = html;
popup.anchorEl = el;
popup.showAnchor(popup.anchorEl);
} else {
popup.hide();
}
}
});
editor.addListener('selectionchange', function (t, causeByUi) {
if (!causeByUi) return;
var html = '', str = "",
img = editor.selection.getRange().getClosedNode(),
dialogs = editor.ui._dialogs;
if (img && img.tagName == 'IMG') {
var dialogName = 'insertimageDialog';
if (img.className.indexOf("edui-faked-video") != -1 || img.className.indexOf("edui-upload-video") != -1) {
dialogName = "insertvideoDialog"
}
if (img.className.indexOf("edui-faked-webapp") != -1) {
dialogName = "webappDialog"
}
if (img.src.indexOf("http://api.map.baidu.com") != -1) {
dialogName = "mapDialog"
}
if (img.className.indexOf("edui-faked-music") != -1) {
dialogName = "musicDialog"
}
if (img.src.indexOf("http://maps.google.com/maps/api/staticmap") != -1) {
dialogName = "gmapDialog"
}
if (img.getAttribute("anchorname")) {
dialogName = "anchorDialog";
html = popup.formatHtml(
'' + editor.getLang("property") + ': ' + editor.getLang("modify") + ' ' +
'' + editor.getLang("delete") + ' ');
}
if (img.getAttribute("word_img")) {
//todo 放到dialog去做查询
editor.word_img = [img.getAttribute("word_img")];
dialogName = "wordimageDialog"
}
if (domUtils.hasClass(img, 'loadingclass') || domUtils.hasClass(img, 'loaderrorclass')) {
dialogName = "";
}
if (!dialogs[dialogName]) {
return;
}
str = '' + editor.getLang("property") + ': ' +
'' + editor.getLang("default") + ' ' +
'' + editor.getLang("justifyleft") + ' ' +
'' + editor.getLang("justifyright") + ' ' +
'' + editor.getLang("justifycenter") + ' ' +
'' + editor.getLang("modify") + ' ';
!html && (html = popup.formatHtml(str))
}
if (editor.ui._dialogs.linkDialog) {
var link = editor.queryCommandValue('link');
var url;
if (link && (url = (link.getAttribute('_href') || link.getAttribute('href', 2)))) {
var txt = url;
if (url.length > 30) {
txt = url.substring(0, 20) + "...";
}
if (html) {
html += '
'
}
html += popup.formatHtml(
'' + editor.getLang("anthorMsg") + ': ' + txt + ' ' +
' ' + editor.getLang("modify") + ' ' +
' ' + editor.getLang("clear") + ' ');
popup.showAnchor(link);
}
}
if (html) {
popup.getDom('content').innerHTML = html;
popup.anchorEl = img || link;
popup.showAnchor(popup.anchorEl);
} else {
popup.hide();
}
});
}
},
_initToolbars: function () {
var editor = this.editor;
var toolbars = this.toolbars || [];
var toolbarUis = [];
for (var i = 0; i < toolbars.length; i++) {
var toolbar = toolbars[i];
var toolbarUi = new baidu.editor.ui.Toolbar({ theme: editor.options.theme });
for (var j = 0; j < toolbar.length; j++) {
var toolbarItem = toolbar[j];
var toolbarItemUi = null;
if (typeof toolbarItem == 'string') {
toolbarItem = toolbarItem.toLowerCase();
if (toolbarItem == '|') {
toolbarItem = 'Separator';
}
if (toolbarItem == '||') {
toolbarItem = 'Breakline';
}
if (baidu.editor.ui[toolbarItem]) {
toolbarItemUi = new baidu.editor.ui[toolbarItem](editor);
}
//fullscreen这里单独处理一下,放到首行去
if (toolbarItem == 'fullscreen') {
if (toolbarUis && toolbarUis[0]) {
toolbarUis[0].items.splice(0, 0, toolbarItemUi);
} else {
toolbarItemUi && toolbarUi.items.splice(0, 0, toolbarItemUi);
}
continue;
}
} else {
toolbarItemUi = toolbarItem;
}
if (toolbarItemUi && toolbarItemUi.id) {
toolbarUi.add(toolbarItemUi);
}
}
toolbarUis[i] = toolbarUi;
}
//接受外部定制的UI
utils.each(UE._customizeUI, function (obj, key) {
var itemUI, index;
if (obj.id && obj.id != editor.key) {
return false;
}
itemUI = obj.execFn.call(editor, editor, key);
if (itemUI) {
index = obj.index;
if (index === undefined) {
index = toolbarUi.items.length;
}
toolbarUi.add(itemUI, index)
}
});
this.toolbars = toolbarUis;
},
getHtmlTpl: function () {
return '' +
'
' +
'
' +
'
' +
//modify wdcount by matao
'
' +
'
' +
'
';
},
showWordImageDialog: function () {
this._dialogs['wordimageDialog'].open();
},
renderToolbarBoxHtml: function () {
var buff = [];
for (var i = 0; i < this.toolbars.length; i++) {
buff.push(this.toolbars[i].renderHtml());
}
return buff.join('');
},
setFullScreen: function (fullscreen) {
var editor = this.editor,
container = editor.container.parentNode.parentNode;
if (this._fullscreen != fullscreen) {
this._fullscreen = fullscreen;
this.editor.fireEvent('beforefullscreenchange', fullscreen);
if (baidu.editor.browser.gecko) {
var bk = editor.selection.getRange().createBookmark();
}
if (fullscreen) {
while (container.tagName != "BODY") {
var position = baidu.editor.dom.domUtils.getComputedStyle(container, "position");
nodeStack.push(position);
container.style.position = "static";
container = container.parentNode;
}
this._bakHtmlOverflow = document.documentElement.style.overflow;
this._bakBodyOverflow = document.body.style.overflow;
this._bakAutoHeight = this.editor.autoHeightEnabled;
this._bakScrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
this._bakEditorContaninerWidth = editor.iframe.parentNode.offsetWidth;
if (this._bakAutoHeight) {
//当全屏时不能执行自动长高
editor.autoHeightEnabled = false;
this.editor.disableAutoHeight();
}
document.documentElement.style.overflow = 'hidden';
//修复,滚动条不收起的问题
window.scrollTo(0, window.scrollY);
this._bakCssText = this.getDom().style.cssText;
this._bakCssText1 = this.getDom('iframeholder').style.cssText;
editor.iframe.parentNode.style.width = '';
this._updateFullScreen();
} else {
while (container.tagName != "BODY") {
container.style.position = nodeStack.shift();
container = container.parentNode;
}
this.getDom().style.cssText = this._bakCssText;
this.getDom('iframeholder').style.cssText = this._bakCssText1;
if (this._bakAutoHeight) {
editor.autoHeightEnabled = true;
this.editor.enableAutoHeight();
}
document.documentElement.style.overflow = this._bakHtmlOverflow;
document.body.style.overflow = this._bakBodyOverflow;
editor.iframe.parentNode.style.width = this._bakEditorContaninerWidth + 'px';
window.scrollTo(0, this._bakScrollTop);
}
if (browser.gecko && editor.body.contentEditable === 'true') {
var input = document.createElement('input');
document.body.appendChild(input);
editor.body.contentEditable = false;
setTimeout(function () {
input.focus();
setTimeout(function () {
editor.body.contentEditable = true;
editor.fireEvent('fullscreenchanged', fullscreen);
editor.selection.getRange().moveToBookmark(bk).select(true);
baidu.editor.dom.domUtils.remove(input);
fullscreen && window.scroll(0, 0);
}, 0)
}, 0)
}
if (editor.body.contentEditable === 'true') {
this.editor.fireEvent('fullscreenchanged', fullscreen);
this.triggerLayout();
}
}
},
_updateFullScreen: function () {
if (this._fullscreen) {
var vpRect = uiUtils.getViewportRect();
this.getDom().style.cssText = 'border:0;position:absolute;left:0;top:' + (this.editor.options.topOffset || 0) + 'px;width:' + vpRect.width + 'px;height:' + vpRect.height + 'px;z-index:' + (this.getDom().style.zIndex * 1 + 100);
uiUtils.setViewportOffset(this.getDom(), { left: 0, top: this.editor.options.topOffset || 0 });
this.editor.setHeight(vpRect.height - this.getDom('toolbarbox').offsetHeight - this.getDom('bottombar').offsetHeight - (this.editor.options.topOffset || 0), true);
//不手动调一下,会导致全屏失效
if (browser.gecko) {
try {
window.onresize();
} catch (e) {
}
}
}
},
_updateElementPath: function () {
var bottom = this.getDom('elementpath'), list;
if (this.elementPathEnabled && (list = this.editor.queryCommandValue('elementpath'))) {
var buff = [];
for (var i = 0, ci; ci = list[i]; i++) {
buff[i] = this.formatHtml('' + ci + ' ');
}
bottom.innerHTML = '' + this.editor.getLang("elementPathTip") + ': ' + buff.join(' > ') + '
';
} else {
bottom.style.display = 'none'
}
},
disableElementPath: function () {
var bottom = this.getDom('elementpath');
bottom.innerHTML = '';
bottom.style.display = 'none';
this.elementPathEnabled = false;
},
enableElementPath: function () {
var bottom = this.getDom('elementpath');
bottom.style.display = '';
this.elementPathEnabled = true;
this._updateElementPath();
},
_scale: function () {
var doc = document,
editor = this.editor,
editorHolder = editor.container,
editorDocument = editor.document,
toolbarBox = this.getDom("toolbarbox"),
bottombar = this.getDom("bottombar"),
scale = this.getDom("scale"),
scalelayer = this.getDom("scalelayer");
var isMouseMove = false,
position = null,
minEditorHeight = 0,
minEditorWidth = editor.options.minFrameWidth,
pageX = 0,
pageY = 0,
scaleWidth = 0,
scaleHeight = 0;
function down() {
position = domUtils.getXY(editorHolder);
if (!minEditorHeight) {
minEditorHeight = editor.options.minFrameHeight + toolbarBox.offsetHeight + bottombar.offsetHeight;
}
scalelayer.style.cssText = "position:absolute;left:0;display:;top:0;background-color:#41ABFF;opacity:0.4;filter: Alpha(opacity=40);width:" + editorHolder.offsetWidth + "px;height:"
+ editorHolder.offsetHeight + "px;z-index:" + (editor.options.zIndex + 1);
domUtils.on(doc, "mousemove", move);
domUtils.on(editorDocument, "mouseup", up);
domUtils.on(doc, "mouseup", up);
}
var me = this;
//by xuheng 全屏时关掉缩放
this.editor.addListener('fullscreenchanged', function (e, fullScreen) {
if (fullScreen) {
me.disableScale();
} else {
if (me.editor.options.scaleEnabled) {
me.enableScale();
var tmpNode = me.editor.document.createElement('span');
me.editor.body.appendChild(tmpNode);
me.editor.body.style.height = Math.max(domUtils.getXY(tmpNode).y, me.editor.iframe.offsetHeight - 20) + 'px';
domUtils.remove(tmpNode)
}
}
});
function move(event) {
clearSelection();
var e = event || window.event;
pageX = e.pageX || (doc.documentElement.scrollLeft + e.clientX);
pageY = e.pageY || (doc.documentElement.scrollTop + e.clientY);
scaleWidth = pageX - position.x;
scaleHeight = pageY - position.y;
if (scaleWidth >= minEditorWidth) {
isMouseMove = true;
scalelayer.style.width = scaleWidth + 'px';
}
if (scaleHeight >= minEditorHeight) {
isMouseMove = true;
scalelayer.style.height = scaleHeight + "px";
}
}
function up() {
if (isMouseMove) {
isMouseMove = false;
editor.ui._actualFrameWidth = scalelayer.offsetWidth - 2;
editorHolder.style.width = editor.ui._actualFrameWidth + 'px';
editor.setHeight(scalelayer.offsetHeight - bottombar.offsetHeight - toolbarBox.offsetHeight - 2, true);
}
if (scalelayer) {
scalelayer.style.display = "none";
}
clearSelection();
domUtils.un(doc, "mousemove", move);
domUtils.un(editorDocument, "mouseup", up);
domUtils.un(doc, "mouseup", up);
}
function clearSelection() {
if (browser.ie)
doc.selection.clear();
else
window.getSelection().removeAllRanges();
}
this.enableScale = function () {
//trace:2868
if (editor.queryCommandState("source") == 1) return;
scale.style.display = "";
this.scaleEnabled = true;
domUtils.on(scale, "mousedown", down);
};
this.disableScale = function () {
scale.style.display = "none";
this.scaleEnabled = false;
domUtils.un(scale, "mousedown", down);
};
},
isFullScreen: function () {
return this._fullscreen;
},
postRender: function () {
UIBase.prototype.postRender.call(this);
for (var i = 0; i < this.toolbars.length; i++) {
this.toolbars[i].postRender();
}
var me = this;
var timerId,
domUtils = baidu.editor.dom.domUtils,
updateFullScreenTime = function () {
clearTimeout(timerId);
timerId = setTimeout(function () {
me._updateFullScreen();
});
};
domUtils.on(window, 'resize', updateFullScreenTime);
me.addListener('destroy', function () {
domUtils.un(window, 'resize', updateFullScreenTime);
clearTimeout(timerId);
})
},
showToolbarMsg: function (msg, flag) {
this.getDom('toolbarmsg_label').innerHTML = msg;
this.getDom('toolbarmsg').style.display = '';
//
if (!flag) {
var w = this.getDom('upload_dialog');
w.style.display = 'none';
}
},
hideToolbarMsg: function () {
this.getDom('toolbarmsg').style.display = 'none';
},
mapUrl: function (url) {
return url ? url.replace('~/', this.editor.options.UEDITOR_HOME_URL || '') : ''
},
triggerLayout: function () {
var dom = this.getDom();
if (dom.style.zoom == '1') {
dom.style.zoom = '100%';
} else {
dom.style.zoom = '1';
}
}
};
utils.inherits(EditorUI, baidu.editor.ui.UIBase);
var instances = {};
UE.ui.Editor = function (options) {
var editor = new UE.Editor(options);
editor.options.editor = editor;
utils.loadFile(document, {
href: editor.options.themePath + editor.options.theme + "/css/ueditor.css",
tag: "link",
type: "text/css",
rel: "stylesheet"
});
var oldRender = editor.render;
editor.render = function (holder) {
if (holder.constructor === String) {
editor.key = holder;
instances[holder] = editor;
}
utils.domReady(function () {
editor.langIsReady ? renderUI() : editor.addListener("langReady", renderUI);
function renderUI() {
editor.setOpt({
labelMap: editor.options.labelMap || editor.getLang('labelMap')
});
new EditorUI(editor.options);
if (holder) {
if (holder.constructor === String) {
holder = document.getElementById(holder);
}
holder && holder.getAttribute('name') && (editor.options.textarea = holder.getAttribute('name'));
if (holder && /script|textarea/ig.test(holder.tagName)) {
var newDiv = document.createElement('div');
holder.parentNode.insertBefore(newDiv, holder);
var cont = holder.value || holder.innerHTML;
editor.options.initialContent = /^[\t\r\n ]*$/.test(cont) ? editor.options.initialContent :
cont.replace(/>[\n\r\t]+([ ]{4})+/g, '>')
.replace(/[\n\r\t]+([ ]{4})+[\n\r\t]+<');
holder.className && (newDiv.className = holder.className);
holder.style.cssText && (newDiv.style.cssText = holder.style.cssText);
if (/textarea/i.test(holder.tagName)) {
editor.textarea = holder;
editor.textarea.style.display = 'none';
} else {
holder.parentNode.removeChild(holder);
}
if (holder.id) {
newDiv.id = holder.id;
domUtils.removeAttributes(holder, 'id');
}
holder = newDiv;
holder.innerHTML = '';
}
}
domUtils.addClass(holder, "edui-" + editor.options.theme);
editor.ui.render(holder);
var opt = editor.options;
//给实例添加一个编辑器的容器引用
editor.container = editor.ui.getDom();
var parents = domUtils.findParents(holder, true);
var displays = [];
for (var i = 0, ci; ci = parents[i]; i++) {
displays[i] = ci.style.display;
ci.style.display = 'block'
}
if (opt.initialFrameWidth) {
opt.minFrameWidth = opt.initialFrameWidth;
} else {
opt.minFrameWidth = opt.initialFrameWidth = holder.offsetWidth;
var styleWidth = holder.style.width;
if (/%$/.test(styleWidth)) {
opt.initialFrameWidth = styleWidth;
}
}
if (opt.initialFrameHeight) {
opt.minFrameHeight = opt.initialFrameHeight;
} else {
opt.initialFrameHeight = opt.minFrameHeight = holder.offsetHeight;
}
for (var i = 0, ci; ci = parents[i]; i++) {
ci.style.display = displays[i]
}
//编辑器最外容器设置了高度,会导致,编辑器不占位
//todo 先去掉,没有找到原因
if (holder.style.height) {
holder.style.height = ''
}
editor.container.style.width = opt.initialFrameWidth + (/%$/.test(opt.initialFrameWidth) ? '' : 'px');
editor.container.style.zIndex = opt.zIndex;
oldRender.call(editor, editor.ui.getDom('iframeholder'));
editor.fireEvent("afteruiready");
}
})
};
return editor;
};
/**
* @file
* @name UE
* @short UE
* @desc UEditor的顶部命名空间
*/
/**
* @name getEditor
* @since 1.2.4+
* @grammar UE.getEditor(id,[opt]) => Editor实例
* @desc 提供一个全局的方法得到编辑器实例
*
* * ''id'' 放置编辑器的容器id, 如果容器下的编辑器已经存在,就直接返回
* * ''opt'' 编辑器的可选参数
* @example
* UE.getEditor('containerId',{onready:function(){//创建一个编辑器实例
* this.setContent('hello')
* }});
* UE.getEditor('containerId'); //返回刚创建的实例
*
*/
UE.getEditor = function (id, opt) {
var editor = instances[id];
if (!editor) {
editor = instances[id] = new UE.ui.Editor(opt);
editor.render(id);
}
return editor;
};
UE.delEditor = function (id) {
var editor;
if (editor = instances[id]) {
editor.key && editor.destroy();
delete instances[id]
}
};
UE.registerUI = function (uiName, fn, index, editorId) {
utils.each(uiName.split(/\s+/), function (name) {
UE._customizeUI[name] = {
id: editorId,
execFn: fn,
index: index
};
})
}
})();
// adapter/message.js
UE.registerUI('message', function (editor) {
var editorui = baidu.editor.ui;
var Message = editorui.Message;
var holder;
var _messageItems = [];
var me = editor;
me.addListener('ready', function () {
holder = document.getElementById(me.ui.id + '_message_holder');
updateHolderPos();
setTimeout(function () {
updateHolderPos();
}, 500);
});
me.addListener('showmessage', function (type, opt) {
opt = utils.isString(opt) ? {
'content': opt
} : opt;
var message = new Message({
'timeout': opt.timeout,
'type': opt.type,
'content': opt.content,
'keepshow': opt.keepshow,
'editor': me
}),
mid = opt.id || ('msg_' + (+new Date()).toString(36));
message.render(holder);
_messageItems[mid] = message;
message.reset(opt);
updateHolderPos();
return mid;
});
me.addListener('updatemessage', function (type, id, opt) {
opt = utils.isString(opt) ? {
'content': opt
} : opt;
var message = _messageItems[id];
message.render(holder);
message && message.reset(opt);
});
me.addListener('hidemessage', function (type, id) {
var message = _messageItems[id];
message && message.hide();
});
function updateHolderPos() {
var toolbarbox = me.ui.getDom('toolbarbox');
if (toolbarbox) {
holder.style.top = toolbarbox.offsetHeight + 3 + 'px';
}
holder.style.zIndex = Math.max(me.options.zIndex, me.iframe.style.zIndex) + 1;
}
});
// adapter/autosave.js
UE.registerUI('autosave', function (editor) {
var timer = null, uid = null;
editor.on('afterautosave', function () {
clearTimeout(timer);
timer = setTimeout(function () {
if (uid) {
editor.trigger('hidemessage', uid);
}
uid = editor.trigger('showmessage', {
content: editor.getLang('autosave.success'),
timeout: 2000
});
}, 2000)
})
});
})();