]/.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;
+
+ }
+ //如果结束是文本,就有可能丢掉,所以这里手动判断一下
+ //例如 sdfsdfsdfsdfsdfsdfsdf
+ 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
+ * //插入后的效果 xxxCCxxx
+ * //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;
+ }
+
+ 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) {
+ str = '';
+ if (ci['floatStyle'] == 'center') {
+ str = '' + str + ' ';
+ }
+ html.push(str);
+
+ } else {
+ for (var i = 0; ci = opt[i++];) {
+ 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
+ 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){
+ var str;
+ switch (type){
+ case 'image':
+ str = ''
+ break;
+ case 'embed':
+ str = ' |