]/.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,
  //以上的正则表达式无法匹配:
  //修改为如下正则表达式:
  var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))/g,
    re_attr = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g;
  //ie下取得的html可能会有\n存在,要去掉,在处理replace(/[\t\r\n]*/g,'');代码高量的\n不能去除
  var allowEmptyTags = {
    b: 1,
    code: 1,
    i: 1,
    u: 1,
    strike: 1,
    s: 1,
    tt: 1,
    strong: 1,
    q: 1,
    samp: 1,
    em: 1,
    span: 1,
    sub: 1,
    img: 1,
    sup: 1,
    font: 1,
    big: 1,
    small: 1,
    iframe: 1,
    a: 1,
    br: 1,
    pre: 1
  };
  htmlstr = htmlstr.replace(new RegExp(domUtils.fillChar, "g"), "");
  if (!ignoreBlank) {
    htmlstr = htmlstr.replace(
      new RegExp(
        "[\\r\\t\\n" +
          (ignoreBlank ? "" : " ") +
          "]*?(\\w+)\\s*(?:[^>]*)>[\\r\\t\\n" +
          (ignoreBlank ? "" : " ") +
          "]*",
        "g"
      ),
      function(a, b) {
        //br暂时单独处理
        if (b && allowEmptyTags[b.toLowerCase()]) {
          return a.replace(/(^[\n\r]+)|([\n\r]+$)/g, "");
        }
        return a
          .replace(new RegExp("^[\\r\\n" + (ignoreBlank ? "" : " ") + "]+"), "")
          .replace(
            new RegExp("[\\r\\n" + (ignoreBlank ? "" : " ") + "]+$"),
            ""
          );
      }
    );
  }
  var notTransAttrs = {
    href: 1,
    src: 1
  };
  var uNode = UE.uNode,
    needParentNode = {
      td: "tr",
      tr: ["tbody", "thead", "tfoot"],
      tbody: "table",
      th: "tr",
      thead: "table",
      tfoot: "table",
      caption: "table",
      li: ["ul", "ol"],
      dt: "dl",
      dd: "dl",
      option: "select"
    },
    needChild = {
      ol: "li",
      ul: "li"
    };
  function text(parent, data) {
    if (needChild[parent.tagName]) {
      var tmpNode = uNode.createElement(needChild[parent.tagName]);
      parent.appendChild(tmpNode);
      tmpNode.appendChild(uNode.createText(data));
      parent = tmpNode;
    } else {
      parent.appendChild(uNode.createText(data));
    }
  }
  function element(parent, tagName, htmlattr) {
    var needParentTag;
    if ((needParentTag = needParentNode[tagName])) {
      var tmpParent = parent,
        hasParent;
      while (tmpParent.type != "root") {
        if (
          utils.isArray(needParentTag)
            ? utils.indexOf(needParentTag, tmpParent.tagName) != -1
            : needParentTag == tmpParent.tagName
        ) {
          parent = tmpParent;
          hasParent = true;
          break;
        }
        tmpParent = tmpParent.parentNode;
      }
      if (!hasParent) {
        parent = element(
          parent,
          utils.isArray(needParentTag) ? needParentTag[0] : needParentTag
        );
      }
    }
    //按dtd处理嵌套
    //        if(parent.type != 'root' && !dtd[parent.tagName][tagName])
    //            parent = parent.parentNode;
    var elm = new uNode({
      parentNode: parent,
      type: "element",
      tagName: tagName.toLowerCase(),
      //是自闭合的处理一下
      children: dtd.$empty[tagName] ? null : []
    });
    //如果属性存在,处理属性
    if (htmlattr) {
      var attrs = {},
        match;
      while ((match = re_attr.exec(htmlattr))) {
        attrs[match[1].toLowerCase()] = notTransAttrs[match[1].toLowerCase()]
          ? match[2] || match[3] || match[4]
          : utils.unhtml(match[2] || match[3] || match[4]);
      }
      elm.attrs = attrs;
    }
    //trace:3970
    //        //如果parent下不能放elm
    //        if(dtd.$inline[parent.tagName] && dtd.$block[elm.tagName] && !dtd[parent.tagName][elm.tagName]){
    //            parent = parent.parentNode;
    //            elm.parentNode = parent;
    //        }
    parent.children.push(elm);
    //如果是自闭合节点返回父亲节点
    return dtd.$empty[tagName] ? parent : elm;
  }
  function comment(parent, data) {
    parent.children.push(
      new uNode({
        type: "comment",
        data: data,
        parentNode: parent
      })
    );
  }
  var match,
    currentIndex = 0,
    nextIndex = 0;
  //设置根节点
  var root = new uNode({
    type: "root",
    children: []
  });
  var currentParent = root;
  while ((match = re_tag.exec(htmlstr))) {
    currentIndex = match.index;
    try {
      if (currentIndex > nextIndex) {
        //text node
        text(currentParent, htmlstr.slice(nextIndex, currentIndex));
      }
      if (match[3]) {
        if (dtd.$cdata[currentParent.tagName]) {
          text(currentParent, match[0]);
        } else {
          //start tag
          currentParent = element(
            currentParent,
            match[3].toLowerCase(),
            match[4]
          );
        }
      } else if (match[1]) {
        if (currentParent.type != "root") {
          if (dtd.$cdata[currentParent.tagName] && !dtd.$cdata[match[1]]) {
            text(currentParent, match[0]);
          } else {
            var tmpParent = currentParent;
            while (
              currentParent.type == "element" &&
              currentParent.tagName != match[1].toLowerCase()
            ) {
              currentParent = currentParent.parentNode;
              if (currentParent.type == "root") {
                currentParent = tmpParent;
                throw "break";
              }
            }
            //end tag
            currentParent = currentParent.parentNode;
          }
        }
      } else if (match[2]) {
        //comment
        comment(currentParent, match[2]);
      }
    } catch (e) {}
    nextIndex = re_tag.lastIndex;
  }
  //如果结束是文本,就有可能丢掉,所以这里手动判断一下
  //例如 sdfsdfsdf sdfsdfsdfsdf
  if (nextIndex < htmlstr.length) {
    text(currentParent, htmlstr.slice(nextIndex));
  }
  return root;
});
// core/filternode.js
/**
 * UE过滤节点的静态方法
 * @file
 */
/**
 * UEditor公用空间,UEditor所有的功能都挂载在该空间下
 * @module UE
 */
/**
 * 根据传入节点和过滤规则过滤相应节点
 * @module UE
 * @since 1.2.6.1
 * @method filterNode
 * @param { Object } root 指定root节点
 * @param { Object } rules 过滤规则json对象
 * @example
 * ```javascript
 * UE.filterNode(root,editor.options.filterRules);
 * ```
 */
var filterNode = (UE.filterNode = (function() {
  function filterNode(node, rules) {
    switch (node.type) {
      case "text":
        break;
      case "element":
        var val;
        if ((val = rules[node.tagName])) {
          if (val === "-") {
            node.parentNode.removeChild(node);
          } else if (utils.isFunction(val)) {
            var parentNode = node.parentNode,
              index = node.getIndex();
            val(node);
            if (node.parentNode) {
              if (node.children) {
                for (var i = 0, ci; (ci = node.children[i]); ) {
                  filterNode(ci, rules);
                  if (ci.parentNode) {
                    i++;
                  }
                }
              }
            } else {
              for (var i = index, ci; (ci = parentNode.children[i]); ) {
                filterNode(ci, rules);
                if (ci.parentNode) {
                  i++;
                }
              }
            }
          } else {
            var attrs = val["$"];
            if (attrs && node.attrs) {
              var tmpAttrs = {},
                tmpVal;
              for (var a in attrs) {
                tmpVal = node.getAttr(a);
                //todo 只先对style单独处理
                if (a == "style" && utils.isArray(attrs[a])) {
                  var tmpCssStyle = [];
                  utils.each(attrs[a], function(v) {
                    var tmp;
                    if ((tmp = node.getStyle(v))) {
                      tmpCssStyle.push(v + ":" + tmp);
                    }
                  });
                  tmpVal = tmpCssStyle.join(";");
                }
                if (tmpVal) {
                  tmpAttrs[a] = tmpVal;
                }
              }
              node.attrs = tmpAttrs;
            }
            if (node.children) {
              for (var i = 0, ci; (ci = node.children[i]); ) {
                filterNode(ci, rules);
                if (ci.parentNode) {
                  i++;
                }
              }
            }
          }
        } else {
          //如果不在名单里扣出子节点并删除该节点,cdata除外
          if (dtd.$cdata[node.tagName]) {
            node.parentNode.removeChild(node);
          } else {
            var parentNode = node.parentNode,
              index = node.getIndex();
            node.parentNode.removeChild(node, true);
            for (var i = index, ci; (ci = parentNode.children[i]); ) {
              filterNode(ci, rules);
              if (ci.parentNode) {
                i++;
              }
            }
          }
        }
        break;
      case "comment":
        node.parentNode.removeChild(node);
    }
  }
  return function(root, rules) {
    if (utils.isEmptyObject(rules)) {
      return root;
    }
    var val;
    if ((val = rules["-"])) {
      utils.each(val.split(" "), function(k) {
        rules[k] = "-";
      });
    }
    for (var i = 0, ci; (ci = root.children[i]); ) {
      filterNode(ci, rules);
      if (ci.parentNode) {
        i++;
      }
    }
    return root;
  };
})());
// core/plugin.js
/**
 * Created with JetBrains PhpStorm.
 * User: campaign
 * Date: 10/8/13
 * Time: 6:15 PM
 * To change this template use File | Settings | File Templates.
 */
UE.plugin = (function() {
  var _plugins = {};
  return {
    register: function(pluginName, fn, oldOptionName, afterDisabled) {
      if (oldOptionName && utils.isFunction(oldOptionName)) {
        afterDisabled = oldOptionName;
        oldOptionName = null;
      }
      _plugins[pluginName] = {
        optionName: oldOptionName || pluginName,
        execFn: fn,
        //当插件被禁用时执行
        afterDisabled: afterDisabled
      };
    },
    load: function(editor) {
      utils.each(_plugins, function(plugin) {
        var _export = plugin.execFn.call(editor);
        if (editor.options[plugin.optionName] !== false) {
          if (_export) {
            //后边需要再做扩展
            utils.each(_export, function(v, k) {
              switch (k.toLowerCase()) {
                case "shortcutkey":
                  editor.addshortcutkey(v);
                  break;
                case "bindevents":
                  utils.each(v, function(fn, eventName) {
                    editor.addListener(eventName, fn);
                  });
                  break;
                case "bindmultievents":
                  utils.each(utils.isArray(v) ? v : [v], function(event) {
                    var types = utils.trim(event.type).split(/\s+/);
                    utils.each(types, function(eventName) {
                      editor.addListener(eventName, event.handler);
                    });
                  });
                  break;
                case "commands":
                  utils.each(v, function(execFn, execName) {
                    editor.commands[execName] = execFn;
                  });
                  break;
                case "outputrule":
                  editor.addOutputRule(v);
                  break;
                case "inputrule":
                  editor.addInputRule(v);
                  break;
                case "defaultoptions":
                  editor.setOpt(v);
              }
            });
          }
        } else if (plugin.afterDisabled) {
          plugin.afterDisabled.call(editor);
        }
      });
      //向下兼容
      utils.each(UE.plugins, function(plugin) {
        plugin.call(editor);
      });
    },
    run: function(pluginName, editor) {
      var plugin = _plugins[pluginName];
      if (plugin) {
        plugin.exeFn.call(editor);
      }
    }
  };
})();
// core/keymap.js
var keymap = (UE.keymap = {
  Backspace: 8,
  Tab: 9,
  Enter: 13,
  Shift: 16,
  Control: 17,
  Alt: 18,
  CapsLock: 20,
  Esc: 27,
  Spacebar: 32,
  PageUp: 33,
  PageDown: 34,
  End: 35,
  Home: 36,
  Left: 37,
  Up: 38,
  Right: 39,
  Down: 40,
  Insert: 45,
  Del: 46,
  NumLock: 144,
  Cmd: 91,
  "=": 187,
  "-": 189,
  b: 66,
  i: 73,
  //回退
  z: 90,
  y: 89,
  //粘贴
  v: 86,
  x: 88,
  s: 83,
  n: 78
});
// core/localstorage.js
//存储媒介封装
var LocalStorage = (UE.LocalStorage = (function() {
  var storage = window.localStorage || getUserData() || null,
    LOCAL_FILE = "localStorage";
  return {
    saveLocalData: function(key, data) {
      if (storage && data) {
        storage.setItem(key, data);
        return true;
      }
      return false;
    },
    getLocalData: function(key) {
      if (storage) {
        return storage.getItem(key);
      }
      return null;
    },
    removeItem: function(key) {
      storage && storage.removeItem(key);
    }
  };
  function getUserData() {
    var container = document.createElement("div");
    container.style.display = "none";
    if (!container.addBehavior) {
      return null;
    }
    container.addBehavior("#default#userdata");
    return {
      getItem: function(key) {
        var result = null;
        try {
          document.body.appendChild(container);
          container.load(LOCAL_FILE);
          result = container.getAttribute(key);
          document.body.removeChild(container);
        } catch (e) {}
        return result;
      },
      setItem: function(key, value) {
        document.body.appendChild(container);
        container.setAttribute(key, value);
        container.save(LOCAL_FILE);
        document.body.removeChild(container);
      },
      //// 暂时没有用到
      //clear: function () {
      //
      //    var expiresTime = new Date();
      //    expiresTime.setFullYear(expiresTime.getFullYear() - 1);
      //    document.body.appendChild(container);
      //    container.expires = expiresTime.toUTCString();
      //    container.save(LOCAL_FILE);
      //    document.body.removeChild(container);
      //
      //},
      removeItem: function(key) {
        document.body.appendChild(container);
        container.removeAttribute(key);
        container.save(LOCAL_FILE);
        document.body.removeChild(container);
      }
    };
  }
})());
;(function() {
  var ROOTKEY = "ueditor_preference";
  UE.Editor.prototype.setPreferences = function(key, value) {
    var obj = {};
    if (utils.isString(key)) {
      obj[key] = value;
    } else {
      obj = key;
    }
    var data = LocalStorage.getLocalData(ROOTKEY);
    if (data && (data = utils.str2json(data))) {
      utils.extend(data, obj);
    } else {
      data = obj;
    }
    data && LocalStorage.saveLocalData(ROOTKEY, utils.json2str(data));
  };
  UE.Editor.prototype.getPreferences = function(key) {
    var data = LocalStorage.getLocalData(ROOTKEY);
    if (data && (data = utils.str2json(data))) {
      return key ? data[key] : data;
    }
    return null;
  };
  UE.Editor.prototype.removePreferences = function(key) {
    var data = LocalStorage.getLocalData(ROOTKEY);
    if (data && (data = utils.str2json(data))) {
      data[key] = undefined;
      delete data[key];
    }
    data && LocalStorage.saveLocalData(ROOTKEY, utils.json2str(data));
  };
})();
// plugins/defaultfilter.js
///import core
///plugin 编辑器默认的过滤转换机制
UE.plugins["defaultfilter"] = function() {
  var me = this;
  me.setOpt({
    allowDivTransToP: true,
    disabledTableInTable: true,
    rgb2Hex: 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 ? " " : "CC 
 * //插入后的效果 xxxCC xxx
 * //xx|xxx
 当前选区为闭合状态
 * //插入CC
 * //结果 xx
CC
xxx
 * //xxxx
|xxx 当前选区在两个p标签之间
 * //插入 xxxx
 * //结果 xxxx
xxxx
xxx
 * ```
 */
UE.commands["inserthtml"] = {
  execCommand: function(command, html, notNeedFilter) {
    var me = this,
      range,
      div;
    if (!html) {
      return;
    }
    if (me.fireEvent("beforeinserthtml", html) === true) {
      return;
    }
    range = me.selection.getRange();
    div = range.document.createElement("div");
    div.style.display = "inline";
    if (!notNeedFilter) {
      var root = UE.htmlparser(html);
      //如果给了过滤规则就先进行过滤
      if (me.options.filterRules) {
        UE.filterNode(root, me.options.filterRules);
      }
      //执行默认的处理
      me.filterInputRule(root);
      html = root.toHtml();
    }
    div.innerHTML = utils.trim(html);
    if (!range.collapsed) {
      var tmpNode = range.startContainer;
      if (domUtils.isFillChar(tmpNode)) {
        range.setStartBefore(tmpNode);
      }
      tmpNode = range.endContainer;
      if (domUtils.isFillChar(tmpNode)) {
        range.setEndAfter(tmpNode);
      }
      range.txtToElmBoundary();
      //结束边界可能放到了br的前边,要把br包含进来
      // x[xxx]" + (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 : "
'
          )
        );
      }
    },
    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") {
              var 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.getElementsByClassName("_img_parent_tmp")[0];
              tmpNode.removeAttribute("class");
              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 =
          '' + 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) {
        rng.traversal(function(node){
          var start;
          if(domUtils.isTagNode(node,'span')){
            start = node;
          }else{
            start = domUtils.getElementsByTagName(node,'span')[0];
          }
          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:'neditor.baidu.com',
 *     title:'neditor',
 *     target:'_blank'
 * }' );
 * ```
 */
/**
 * 返回当前选中的第一个超链接节点
 * @command link
 * @method queryCommandValue
 * @param { String } cmd 命令字符串
 * @return { Element } 超链接节点
 * @example
 * ```javascript
 * editor.queryCommandValue( 'link' );
 * ```
 */
/**
 * 取消超链接
 * @command unlink
 * @method execCommand
 * @param { String } cmd 命令字符串
 * @example
 * ```javascript
 * editor.execCommand( 'unlink');
 * ```
 */
UE.plugins["link"] = function() {
  function optimize(range) {
    var start = range.startContainer,
      end = range.endContainer;
    if ((start = domUtils.findParentByTagName(start, "a", true))) {
      range.setStartBefore(start);
    }
    if ((end = domUtils.findParentByTagName(end, "a", true))) {
      range.setEndAfter(end);
    }
  }
  UE.commands["unlink"] = {
    execCommand: function() {
      var range = this.selection.getRange(),
        bookmark;
      if (
        range.collapsed &&
        !domUtils.findParentByTagName(range.startContainer, "a", true)
      ) {
        return;
      }
      bookmark = range.createBookmark();
      optimize(range);
      range.removeInlineStyle("a").moveToBookmark(bookmark).select();
    },
    queryCommandState: function() {
      return !this.highlight && this.queryCommandValue("link") ? 0 : -1;
    }
  };
  function doLink(range, opt, me) {
    var rngClone = range.cloneRange(),
      link = me.queryCommandValue("link");
    optimize((range = range.adjustmentBoundary()));
    var start = range.startContainer;
    if (start.nodeType == 1 && link) {
      start = start.childNodes[range.startOffset];
      if (
        start &&
        start.nodeType == 1 &&
        start.tagName == "A" &&
        /^(?:https?|ftp|file)\s*:\s*\/\//.test(
          start[browser.ie ? "innerText" : "textContent"]
        )
      ) {
        start[browser.ie ? "innerText" : "textContent"] = utils.html(
          opt.textValue || opt.href
        );
      }
    }
    if (!rngClone.collapsed || link) {
      range.removeInlineStyle("a");
      rngClone = range.cloneRange();
    }
    if (rngClone.collapsed) {
      var a = range.document.createElement("a"),
        text = "";
      if (opt.textValue) {
        text = utils.html(opt.textValue);
        delete opt.textValue;
      } else {
        text = utils.html(opt.href);
      }
      domUtils.setAttributes(a, opt);
      start = domUtils.findParentByTagName(rngClone.startContainer, "a", true);
      if (start && domUtils.isInNodeEndBoundary(rngClone, start)) {
        range.setStartAfter(start).collapse(true);
      }
      a[browser.ie ? "innerText" : "textContent"] = text;
      range.insertNode(a).selectNode(a);
    } else {
      range.applyInlineStyle("a", opt);
    }
  }
  UE.commands["link"] = {
    execCommand: function(cmdName, opt) {
      var range;
      opt._href && (opt._href = utils.unhtml(opt._href, /[<">]/g));
      opt.href && (opt.href = utils.unhtml(opt.href, /[<">]/g));
      opt.textValue && (opt.textValue = utils.unhtml(opt.textValue, /[<">]/g));
      doLink((range = this.selection.getRange()), opt, this);
      //闭合都不加占位符,如果加了会在a后边多个占位符节点,导致a是图片背景组成的列表,出现空白问题
      range.collapse().select(true);
    },
    queryCommandValue: function() {
      var range = this.selection.getRange(),
        node;
      if (range.collapsed) {
        //                    node = this.selection.getStart();
        //在ie下getstart()取值偏上了
        node = range.startContainer;
        node = node.nodeType == 1 ? node : node.parentNode;
        if (
          node &&
          (node = domUtils.findParentByTagName(node, "a", true)) &&
          !domUtils.isInNodeEndBoundary(range, node)
        ) {
          return node;
        }
      } else {
        //trace:1111  如果是xx 
 startContainer是p就会找不到a
        range.shrinkBoundary();
        var start = range.startContainer.nodeType == 3 ||
          !range.startContainer.childNodes[range.startOffset]
          ? range.startContainer
          : range.startContainer.childNodes[range.startOffset],
          end = range.endContainer.nodeType == 3 || range.endOffset == 0
            ? range.endContainer
            : range.endContainer.childNodes[range.endOffset - 1],
          common = range.getCommonAncestor();
        node = domUtils.findParentByTagName(common, "a", true);
        if (!node && common.nodeType == 1) {
          var as = common.getElementsByTagName("a"),
            ps,
            pe;
          for (var i = 0, ci; (ci = as[i++]); ) {
            (ps = domUtils.getPosition(ci, start)), (pe = domUtils.getPosition(
              ci,
              end
            ));
            if (
              (ps & domUtils.POSITION_FOLLOWING ||
                ps & domUtils.POSITION_CONTAINS) &&
              (pe & domUtils.POSITION_PRECEDING ||
                pe & domUtils.POSITION_CONTAINS)
            ) {
              node = ci;
              break;
            }
          }
        }
        return node;
      }
    },
    queryCommandState: function() {
      //判断如果是视频的话连接不可用
      //fix 853
      var img = this.selection.getRange().getClosedNode(),
        flag =
          img &&
          (img.className == "edui-faked-video" ||
            img.className.indexOf("edui-upload-video") != -1);
      return flag ? -1 : 0;
    }
  };
};
// plugins/iframe.js
///import core
///import plugins\inserthtml.js
///commands 插入框架
///commandsName  InsertFrame
///commandsTitle  插入Iframe
///commandsDialog  dialogs\insertframe
UE.plugins["insertframe"] = function() {
  var me = this;
  function deleteIframe() {
    me._iframe && delete me._iframe;
  }
  me.addListener("selectionchange", function() {
    deleteIframe();
  });
};
// plugins/scrawl.js
///import core
///commands 涂鸦
///commandsName  Scrawl
///commandsTitle  涂鸦
///commandsDialog  dialogs\scrawl
UE.commands["scrawl"] = {
  queryCommandState: function() {
    return browser.ie && browser.version <= 8 ? -1 : 0;
  }
};
// plugins/removeformat.js
/**
 * 清除格式
 * @file
 * @since 1.2.6.1
 */
/**
 * 清除文字样式
 * @command removeformat
 * @method execCommand
 * @param { String } cmd 命令字符串
 * @param   {String}   tags     以逗号隔开的标签。如:strong
 * @param   {String}   style    样式如:color
 * @param   {String}   attrs    属性如:width
 * @example
 * ```javascript
 * editor.execCommand( 'removeformat', 'strong','color','width' );
 * ```
 */
UE.plugins["removeformat"] = function() {
  var me = this;
  me.setOpt({
    removeFormatTags:
      "b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var",
    removeFormatAttributes: "class,style,lang,width,height,align,hspace,valign"
  });
  me.commands["removeformat"] = {
    execCommand: function(cmdName, tags, style, attrs, notIncludeA) {
      var tagReg = new RegExp(
        "^(?:" +
          (tags || this.options.removeFormatTags).replace(/,/g, "|") +
          ")$",
        "i"
      ),
        removeFormatAttributes = style
          ? []
          : (attrs || this.options.removeFormatAttributes).split(","),
        range = new dom.Range(this.document),
        bookmark,
        node,
        parent,
        filter = function(node) {
          return node.nodeType == 1;
        };
      function isRedundantSpan(node) {
        if (node.nodeType == 3 || node.tagName.toLowerCase() != "span") {
          return 0;
        }
        if (browser.ie) {
          //ie 下判断实效,所以只能简单用style来判断
          //return node.style.cssText == '' ? 1 : 0;
          var attrs = node.attributes;
          if (attrs.length) {
            for (var i = 0, l = attrs.length; i < l; i++) {
              if (attrs[i].specified) {
                return 0;
              }
            }
            return 1;
          }
        }
        return !node.attributes.length;
      }
      function doRemove(range) {
        var bookmark1 = range.createBookmark();
        if (range.collapsed) {
          range.enlarge(true);
        }
        //不能把a标签切了
        if (!notIncludeA) {
          var aNode = domUtils.findParentByTagName(
            range.startContainer,
            "a",
            true
          );
          if (aNode) {
            range.setStartBefore(aNode);
          }
          aNode = domUtils.findParentByTagName(range.endContainer, "a", true);
          if (aNode) {
            range.setEndAfter(aNode);
          }
        }
        bookmark = range.createBookmark();
        node = bookmark.start;
        //切开始
        while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) {
          domUtils.breakParent(node, parent);
          domUtils.clearEmptySibling(node);
        }
        if (bookmark.end) {
          //切结束
          node = bookmark.end;
          while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) {
            domUtils.breakParent(node, parent);
            domUtils.clearEmptySibling(node);
          }
          //开始去除样式
          var current = domUtils.getNextDomNode(bookmark.start, false, filter),
            next;
          while (current) {
            if (current == bookmark.end) {
              break;
            }
            next = domUtils.getNextDomNode(current, true, filter);
            if (
              !dtd.$empty[current.tagName.toLowerCase()] &&
              !domUtils.isBookmarkNode(current)
            ) {
              if (tagReg.test(current.tagName)) {
                if (style) {
                  domUtils.removeStyle(current, style);
                  if (isRedundantSpan(current) && style != "text-decoration") {
                    domUtils.remove(current, true);
                  }
                } else {
                  domUtils.remove(current, true);
                }
              } else {
                //trace:939  不能把list上的样式去掉
                if (
                  !dtd.$tableContent[current.tagName] &&
                  !dtd.$list[current.tagName]
                ) {
                  domUtils.removeAttributes(current, removeFormatAttributes);
                  if (isRedundantSpan(current)) {
                    domUtils.remove(current, true);
                  }
                }
              }
            }
            current = next;
          }
        }
        //trace:1035
        //trace:1096 不能把td上的样式去掉,比如边框
        var pN = bookmark.start.parentNode;
        if (
          domUtils.isBlockElm(pN) &&
          !dtd.$tableContent[pN.tagName] &&
          !dtd.$list[pN.tagName]
        ) {
          domUtils.removeAttributes(pN, removeFormatAttributes);
        }
        pN = bookmark.end.parentNode;
        if (
          bookmark.end &&
          domUtils.isBlockElm(pN) &&
          !dtd.$tableContent[pN.tagName] &&
          !dtd.$list[pN.tagName]
        ) {
          domUtils.removeAttributes(pN, removeFormatAttributes);
        }
        range.moveToBookmark(bookmark).moveToBookmark(bookmark1);
        //清除冗余的代码 " +
        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.parentNode, 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", "' +
            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 = "" + (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")) {
          //过滤掉word冗余标签
          //_Toc\d+有可能勿命中
          if (/^\_Toc\d+$/.test(val)) {
            a.parentNode.removeChild(a);
            return;
          }
          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(
          '
";
            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 ? " " : "
";
              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;
        },
         focus: function (){
           textarea.focus();
        },
         blur: function (){
           textarea.blur();
        }
      };
    },
    codemirror: function(editor, holder) {
      var codeEditor = window.CodeMirror(holder, {
        mode: "text/html",
        tabMode: "indent",
        lineNumbers: true,
        lineWrapping: true
      });
      var dom = codeEditor.getWrapperElement();
      dom.style.cssText =
        'position:absolute;left:0;top:0;width:100%;height:100%;font-family:consolas,"Courier new",monospace;font-size:13px;';
      codeEditor.getScrollerElement().style.cssText =
        "position:absolute;left:0;top:0;width:100%;height:100%;";
      codeEditor.refresh();
      return {
        getCodeMirror: function() {
          return codeEditor;
        },
        setContent: function(content) {
          codeEditor.setValue(content);
        },
        getContent: function() {
          return codeEditor.getValue();
        },
        select: function() {
          codeEditor.focus();
        },
        dispose: function() {
          holder.removeChild(dom);
          dom = null;
          codeEditor = null;
        },
        focus: function (){
          codeEditor.focus();
        },
        blur: function (){
          // codeEditor.blur();
          // since codemirror not support blur()
           codeEditor.setOption('readOnly', true);
           codeEditor.setOption('readOnly', false);
        }
      };
    }
  };
  UE.plugins["source"] = function() {
    var me = this;
    var opt = this.options;
    var sourceMode = false;
    var sourceEditor;
    var orgSetContent;
    var orgFocus;
    var orgBlur;
    opt.sourceEditor = browser.ie
      ? "textarea"
      : opt.sourceEditor || "codemirror";
    me.setOpt({
      sourceEditorFirst: false
    });
    function createSourceEditor(holder) {
      return sourceEditors[
        opt.sourceEditor == "codemirror" && window.CodeMirror
          ? "codemirror"
          : "textarea"
      ](me, holder);
    }
    var bakCssText;
    //解决在源码模式下getContent不能得到最新的内容问题
    var oldGetContent, bakAddress;
    /**
         * 切换源码模式和编辑模式
         * @command source
         * @method execCommand
         * @param { String } cmd 命令字符串
         * @example
         * ```javascript
         * editor.execCommand( 'source');
         * ```
         */
    /**
         * 查询当前编辑区域的状态是源码模式还是可视化模式
         * @command source
         * @method queryCommandState
         * @param { String } cmd 命令字符串
         * @return { int } 如果当前是源码编辑模式,返回1,否则返回0
         * @example
         * ```javascript
         * editor.queryCommandState( 'source' );
         * ```
         */
    me.commands["source"] = {
      execCommand: function() {
        sourceMode = !sourceMode;
        if (sourceMode) {
          bakAddress = me.selection.getRange().createAddress(false, true);
          me.undoManger && me.undoManger.save(true);
          if (browser.gecko) {
            me.body.contentEditable = false;
          }
          bakCssText = me.iframe.style.cssText;
          me.iframe.style.cssText +=
            "position:absolute;left:-32768px;top:-32768px;";
          me.fireEvent("beforegetcontent");
          var root = UE.htmlparser(me.body.innerHTML);
          me.filterOutputRule(root);
          root.traversal(function(node) {
            if (node.type == "element") {
              switch (node.tagName) {
                case "td":
                case "th":
                case "caption":
                  if (node.children && node.children.length == 1) {
                    if (node.firstChild().tagName == "br") {
                      node.removeChild(node.firstChild());
                    }
                  }
                  break;
                case "pre":
                  node.innerText(node.innerText().replace(/ /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 ? "" : "
"
            );
          };
           orgFocus = me.focus;
           orgBlur = me.blur;
 
           me.focus = function(){
             sourceEditor.focus();
           };
 
           me.blur = function(){
             orgBlur.call(me);
             sourceEditor.blur();
           };
        } else {
          me.iframe.style.cssText = bakCssText;
          var cont =
            sourceEditor.getContent() ||
            "" + (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;
          me.focus = orgFocus;
          me.blur = orgBlur;
          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]
" + (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;
        }
      }
    }
    /* 修复在编辑区域快捷键 (Mac:meta+alt+I; Win:ctrl+shift+I) 打不开 chrome 控制台的问题 */
    browser.chrome &&
      me.on("keydown", function(type, e) {
        var keyCode = e.keyCode || e.which;
        if (
          ((e.metaKey && e.altKey) || (e.ctrlKey && e.shiftKey)) &&
          keyCode == 73
        ) {
          return true;
        }
      });
  });
  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 : "';
        break;
      case "video":
        var ext = url.substr(url.lastIndexOf(".") + 1);
        if (ext == "ogv") ext = "ogg";
        str =
          "' +
          ' ';
        break;
    }
    return str;
  }
  function switchImgAndVideo(root, img2video) {
    utils.each(
      root.getNodesByTagName(img2video ? "img" : "embed video"),
      function(node) {
        var className = node.getAttr("class");
        if (className && className.indexOf("edui-faked-video") != -1) {
          var html = creatInsertStr(
            img2video ? node.getAttr("_url") : node.getAttr("src"),
            node.getAttr("width"),
            node.getAttr("height"),
            null,
            node.getStyle("float") || "",
            className,
            img2video ? "embed" : "image"
          );
          node.parentNode.replaceChild(UE.uNode.createElement(html), node);
        }
        if (className && className.indexOf("edui-upload-video") != -1) {
          var html = creatInsertStr(
            img2video ? node.getAttr("_url") : node.getAttr("src"),
            node.getAttr("width"),
            node.getAttr("height"),
            null,
            node.getStyle("float") || "",
            className,
            img2video ? "video" : "image"
          );
          node.parentNode.replaceChild(UE.uNode.createElement(html), node);
        }
      }
    );
  }
  me.addOutputRule(function(root) {
    switchImgAndVideo(root, true);
  });
  me.addInputRule(function(root) {
    switchImgAndVideo(root);
  });
  /**
     * 插入视频
     * @command insertvideo
     * @method execCommand
     * @param { String } cmd 命令字符串
     * @param { Object } videoAttr 键值对对象, 描述一个视频的所有属性
     * @example
     * ```javascript
     *
     * var videoAttr = {
     *      //视频地址
     *      url: 'http://www.youku.com/xxx',
     *      //视频宽高值, 单位px
     *      width: 200,
     *      height: 100
     * };
     *
     * //editor 是编辑器实例
     * //向编辑器插入单个视频
     * editor.execCommand( 'insertvideo', videoAttr );
     * ```
     */
  /**
     * 插入视频
     * @command insertvideo
     * @method execCommand
     * @param { String } cmd 命令字符串
     * @param { Array } videoArr 需要插入的视频的数组, 其中的每一个元素都是一个键值对对象, 描述了一个视频的所有属性
     * @example
     * ```javascript
     *
     * var videoAttr1 = {
     *      //视频地址
     *      url: 'http://www.youku.com/xxx',
     *      //视频宽高值, 单位px
     *      width: 200,
     *      height: 100
     * },
     * videoAttr2 = {
     *      //视频地址
     *      url: 'http://www.youku.com/xxx',
     *      //视频宽高值, 单位px
     *      width: 200,
     *      height: 100
     * }
     *
     * //editor 是编辑器实例
     * //该方法将会向编辑器内插入两个视频
     * editor.execCommand( 'insertvideo', [ videoAttr1, videoAttr2 ] );
     * ```
     */
  /**
     * 查询当前光标所在处是否是一个视频
     * @command insertvideo
     * @method queryCommandState
     * @param { String } cmd 需要查询的命令字符串
     * @return { int } 如果当前光标所在处的元素是一个视频对象, 则返回1,否则返回0
     * @example
     * ```javascript
     *
     * //editor 是编辑器实例
     * editor.queryCommandState( 'insertvideo' );
     * ```
     */
  me.commands["insertvideo"] = {
    execCommand: function(cmd, videoObjs, type) {
      videoObjs = utils.isArray(videoObjs) ? videoObjs : [videoObjs];
      if (me.fireEvent("beforeinsertvideo", videoObjs) === true) {
        return;
      }
      var html = [],
        id = "tmpVedio",
        cl;
      for (var i = 0, vi, len = videoObjs.length; i < len; i++) {
        vi = videoObjs[i];
        cl = type == "upload"
          ? "edui-upload-video video-js vjs-default-skin"
          : "edui-faked-video";
        html.push(
          creatInsertStr(
            vi.url,
            vi.width || 420,
            vi.height || 280,
            id + i,
            null,
            cl,
            "image"
          )
        );
      }
      me.execCommand("inserthtml", html.join(""), true);
      var rng = this.selection.getRange();
      for (var i = 0, len = videoObjs.length; i < len; i++) {
        var img = this.document.getElementById("tmpVedio" + i);
        domUtils.removeAttributes(img, "id");
        rng.selectNode(img).select();
        me.execCommand("imagefloat", videoObjs[i].align);
      }
      me.fireEvent("afterinsertvideo", videoObjs);
    },
    queryCommandState: function() {
      var img = me.selection.getRange().getClosedNode(),
        flag =
          img &&
          (img.className == "edui-faked-video" ||
            img.className.indexOf("edui-upload-video") != -1);
      return flag ? 1 : 0;
    }
  };
};
// plugins/table.core.js
/**
 * Created with JetBrains WebStorm.
 * User: taoqili
 * Date: 13-1-18
 * Time: 上午11:09
 * To change this template use File | Settings | File Templates.
 */
/**
 * UE表格操作类
 * @param table
 * @constructor
 */
;(function() {
  var UETable = (UE.UETable = function(table) {
    this.table = table;
    this.indexTable = [];
    this.selectedTds = [];
    this.cellsRange = {};
    this.update(table);
  });
  //===以下为静态工具方法===
  UETable.removeSelectedClass = function(cells) {
    utils.each(cells, function(cell) {
      domUtils.removeClasses(cell, "selectTdClass");
    });
  };
  UETable.addSelectedClass = function(cells) {
    utils.each(cells, function(cell) {
      domUtils.addClass(cell, "selectTdClass");
    });
  };
  UETable.isEmptyBlock = function(node) {
    var reg = new RegExp(domUtils.fillChar, "g");
    if (
      node[browser.ie ? "innerText" : "textContent"]
        .replace(/^\s*$/, "")
        .replace(reg, "").length > 0
    ) {
      return 0;
    }
    for (var i in dtd.$isNotEmpty)
      if (dtd.$isNotEmpty.hasOwnProperty(i)) {
        if (node.getElementsByTagName(i).length) {
          return 0;
        }
      }
    return 1;
  };
  UETable.getWidth = function(cell) {
    if (!cell) return 0;
    return parseInt(domUtils.getComputedStyle(cell, "width"), 10);
  };
  /**
     * 获取单元格或者单元格组的“对齐”状态。 如果当前的检测对象是一个单元格组, 只有在满足所有单元格的 水平和竖直 对齐属性都相同的
     * 条件时才会返回其状态值,否则将返回null; 如果当前只检测了一个单元格, 则直接返回当前单元格的对齐状态;
     * @param table cell or table cells , 支持单个单元格dom对象 或者 单元格dom对象数组
     * @return { align: 'left' || 'right' || 'center', valign: 'top' || 'middle' || 'bottom' } 或者 null
     */
  UETable.getTableCellAlignState = function(cells) {
    !utils.isArray(cells) && (cells = [cells]);
    var result = {},
      status = ["align", "valign"],
      tempStatus = null,
      isSame = true; //状态是否相同
    utils.each(cells, function(cellNode) {
      utils.each(status, function(currentState) {
        tempStatus = cellNode.getAttribute(currentState);
        if (!result[currentState] && tempStatus) {
          result[currentState] = tempStatus;
        } else if (
          !result[currentState] ||
          tempStatus !== result[currentState]
        ) {
          isSame = false;
          return false;
        }
      });
      return isSame;
    });
    return isSame ? result : null;
  };
  /**
     * 根据当前选区获取相关的table信息
     * @return {Object}
     */
  UETable.getTableItemsByRange = function(editor) {
    var start = editor.selection.getStart();
    //ff下会选中bookmark
    if (
      start &&
      start.id &&
      start.id.indexOf("_baidu_bookmark_start_") === 0 &&
      start.nextSibling
    ) {
      start = start.nextSibling;
    }
    //在table或者td边缘有可能存在选中tr的情况
    var cell = start && domUtils.findParentByTagName(start, ["td", "th"], true),
      tr = cell && cell.parentNode,
      table = tr && domUtils.findParentByTagName(tr, ["table"]),
      caption = table && table.getElementsByTagName("caption")[0];
    return {
      cell: cell,
      tr: tr,
      table: table,
      caption: caption
    };
  };
  UETable.getUETableBySelected = function(editor) {
    var table = UETable.getTableItemsByRange(editor).table;
    if (table && table.ueTable && table.ueTable.selectedTds.length) {
      return table.ueTable;
    }
    return null;
  };
  UETable.getDefaultValue = function(editor, table) {
    var borderMap = {
      thin: "0px",
      medium: "1px",
      thick: "2px"
    },
      tableBorder,
      tdPadding,
      tdBorder,
      tmpValue;
    if (!table) {
      table = editor.document.createElement("table");
      table.insertRow(0).insertCell(0).innerHTML = "xxx";
      editor.body.appendChild(table);
      var td = table.getElementsByTagName("td")[0];
      tmpValue = domUtils.getComputedStyle(table, "border-left-width");
      tableBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
      tmpValue = domUtils.getComputedStyle(td, "padding-left");
      tdPadding = parseInt(borderMap[tmpValue] || tmpValue, 10);
      tmpValue = domUtils.getComputedStyle(td, "border-left-width");
      tdBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
      domUtils.remove(table);
      return {
        tableBorder: tableBorder,
        tdPadding: tdPadding,
        tdBorder: tdBorder
      };
    } else {
      td = table.getElementsByTagName("td")[0];
      tmpValue = domUtils.getComputedStyle(table, "border-left-width");
      tableBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
      tmpValue = domUtils.getComputedStyle(td, "padding-left");
      tdPadding = parseInt(borderMap[tmpValue] || tmpValue, 10);
      tmpValue = domUtils.getComputedStyle(td, "border-left-width");
      tdBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
      return {
        tableBorder: tableBorder,
        tdPadding: tdPadding,
        tdBorder: tdBorder
      };
    }
  };
  /**
     * 根据当前点击的td或者table获取索引对象
     * @param tdOrTable
     */
  UETable.getUETable = function(tdOrTable) {
    var tag = tdOrTable.tagName.toLowerCase();
    tdOrTable = tag == "td" || tag == "th" || tag == "caption"
      ? domUtils.findParentByTagName(tdOrTable, "table", true)
      : tdOrTable;
    if (!tdOrTable.ueTable) {
      tdOrTable.ueTable = new UETable(tdOrTable);
    }
    return tdOrTable.ueTable;
  };
  UETable.cloneCell = function(cell, ignoreMerge, keepPro) {
    if (!cell || utils.isString(cell)) {
      return this.table.ownerDocument.createElement(cell || "td");
    }
    var flag = domUtils.hasClass(cell, "selectTdClass");
    flag && domUtils.removeClasses(cell, "selectTdClass");
    var tmpCell = cell.cloneNode(true);
    if (ignoreMerge) {
      tmpCell.rowSpan = tmpCell.colSpan = 1;
    }
    //去掉宽高
    !keepPro && domUtils.removeAttributes(tmpCell, "width height");
    !keepPro && domUtils.removeAttributes(tmpCell, "style");
    tmpCell.style.borderLeftStyle = "";
    tmpCell.style.borderTopStyle = "";
    tmpCell.style.borderLeftColor = cell.style.borderRightColor;
    tmpCell.style.borderLeftWidth = cell.style.borderRightWidth;
    tmpCell.style.borderTopColor = cell.style.borderBottomColor;
    tmpCell.style.borderTopWidth = cell.style.borderBottomWidth;
    flag && domUtils.addClass(cell, "selectTdClass");
    return tmpCell;
  };
  UETable.prototype = {
    getMaxRows: function() {
      var rows = this.table.rows,
        maxLen = 1;
      for (var i = 0, row; (row = rows[i]); i++) {
        var currentMax = 1;
        for (var j = 0, cj; (cj = row.cells[j++]); ) {
          currentMax = Math.max(cj.rowSpan || 1, currentMax);
        }
        maxLen = Math.max(currentMax + i, maxLen);
      }
      return maxLen;
    },
    /**
         * 获取当前表格的最大列数
         */
    getMaxCols: function() {
      var rows = this.table.rows,
        maxLen = 0,
        cellRows = {};
      for (var i = 0, row; (row = rows[i]); i++) {
        var cellsNum = 0;
        for (var j = 0, cj; (cj = row.cells[j++]); ) {
          cellsNum += cj.colSpan || 1;
          if (cj.rowSpan && cj.rowSpan > 1) {
            for (var k = 1; k < cj.rowSpan; k++) {
              if (!cellRows["row_" + (i + k)]) {
                cellRows["row_" + (i + k)] = cj.colSpan || 1;
              } else {
                cellRows["row_" + (i + k)]++;
              }
            }
          }
        }
        cellsNum += cellRows["row_" + i] || 0;
        maxLen = Math.max(cellsNum, maxLen);
      }
      return maxLen;
    },
    getCellColIndex: function(cell) {},
    /**
         * 获取当前cell旁边的单元格,
         * @param cell
         * @param right
         */
    getHSideCell: function(cell, right) {
      try {
        var cellInfo = this.getCellInfo(cell),
          previewRowIndex,
          previewColIndex;
        var len = this.selectedTds.length,
          range = this.cellsRange;
        //首行或者首列没有前置单元格
        if (
          (!right && (!len ? !cellInfo.colIndex : !range.beginColIndex)) ||
          (right &&
            (!len
              ? cellInfo.colIndex == this.colsNum - 1
              : range.endColIndex == this.colsNum - 1))
        )
          return null;
        previewRowIndex = !len ? cellInfo.rowIndex : range.beginRowIndex;
        previewColIndex = !right
          ? !len
            ? cellInfo.colIndex < 1 ? 0 : cellInfo.colIndex - 1
            : range.beginColIndex - 1
          : !len ? cellInfo.colIndex + 1 : range.endColIndex + 1;
        return this.getCell(
          this.indexTable[previewRowIndex][previewColIndex].rowIndex,
          this.indexTable[previewRowIndex][previewColIndex].cellIndex
        );
      } catch (e) {
        showError(e);
      }
    },
    getTabNextCell: function(cell, preRowIndex) {
      var cellInfo = this.getCellInfo(cell),
        rowIndex = preRowIndex || cellInfo.rowIndex,
        colIndex = cellInfo.colIndex + 1 + (cellInfo.colSpan - 1),
        nextCell;
      try {
        nextCell = this.getCell(
          this.indexTable[rowIndex][colIndex].rowIndex,
          this.indexTable[rowIndex][colIndex].cellIndex
        );
      } catch (e) {
        try {
          rowIndex = rowIndex * 1 + 1;
          colIndex = 0;
          nextCell = this.getCell(
            this.indexTable[rowIndex][colIndex].rowIndex,
            this.indexTable[rowIndex][colIndex].cellIndex
          );
        } catch (e) {}
      }
      return nextCell;
    },
    /**
         * 获取视觉上的后置单元格
         * @param cell
         * @param bottom
         */
    getVSideCell: function(cell, bottom, ignoreRange) {
      try {
        var cellInfo = this.getCellInfo(cell),
          nextRowIndex,
          nextColIndex;
        var len = this.selectedTds.length && !ignoreRange,
          range = this.cellsRange;
        //末行或者末列没有后置单元格
        if (
          (!bottom && cellInfo.rowIndex == 0) ||
          (bottom &&
            (!len
              ? cellInfo.rowIndex + cellInfo.rowSpan > this.rowsNum - 1
              : range.endRowIndex == this.rowsNum - 1))
        )
          return null;
        nextRowIndex = !bottom
          ? !len ? cellInfo.rowIndex - 1 : range.beginRowIndex - 1
          : !len ? cellInfo.rowIndex + cellInfo.rowSpan : range.endRowIndex + 1;
        nextColIndex = !len ? cellInfo.colIndex : range.beginColIndex;
        return this.getCell(
          this.indexTable[nextRowIndex][nextColIndex].rowIndex,
          this.indexTable[nextRowIndex][nextColIndex].cellIndex
        );
      } catch (e) {
        showError(e);
      }
    },
    /**
         * 获取相同结束位置的单元格,xOrY指代了是获取x轴相同还是y轴相同
         */
    getSameEndPosCells: function(cell, xOrY) {
      try {
        var flag = xOrY.toLowerCase() === "x",
          end =
            domUtils.getXY(cell)[flag ? "x" : "y"] +
            cell["offset" + (flag ? "Width" : "Height")],
          rows = this.table.rows,
          cells = null,
          returns = [];
        for (var i = 0; i < this.rowsNum; i++) {
          cells = rows[i].cells;
          for (var j = 0, tmpCell; (tmpCell = cells[j++]); ) {
            var tmpEnd =
              domUtils.getXY(tmpCell)[flag ? "x" : "y"] +
              tmpCell["offset" + (flag ? "Width" : "Height")];
            //对应行的td已经被上面行rowSpan了
            if (tmpEnd > end && flag) break;
            if (cell == tmpCell || end == tmpEnd) {
              //只获取单一的单元格
              //todo 仅获取单一单元格在特定情况下会造成returns为空,从而影响后续的拖拽实现,修正这个。需考虑性能
              if (tmpCell[flag ? "colSpan" : "rowSpan"] == 1) {
                returns.push(tmpCell);
              }
              if (flag) break;
            }
          }
        }
        return returns;
      } catch (e) {
        showError(e);
      }
    },
    setCellContent: function(cell, content) {
      cell.innerHTML = content || (browser.ie ? domUtils.fillChar : "");
          for (var c = 0; c < colsNum; c++) {
            html.push(
              '' +
                (browser.ie && browser.version < 11
                  ? domUtils.fillChar
                  : " "
            );
          }
          html.push(" ");
        }
        //禁止指定table-width
        return "";
      }
      if (!opt) {
        opt = utils.extend(
          {},
          {
            numCols: this.options.defaultCols,
            numRows: this.options.defaultRows,
            tdvalign: this.options.tdvalign
          }
        );
      }
      var me = this;
      var range = this.selection.getRange(),
        start = range.startContainer,
        firstParentBlock =
          domUtils.findParent(
            start,
            function(node) {
              return domUtils.isBlockElm(node);
            },
            true
          ) || me.body;
      var defaultValue = getDefaultValue(me),
        tableWidth = firstParentBlock.offsetWidth,
        tdWidth = Math.floor(
          tableWidth / opt.numCols -
            defaultValue.tdPadding * 2 -
            defaultValue.tdBorder
        );
      //todo其他属性
      !opt.tdvalign && (opt.tdvalign = me.options.tdvalign);
      me.execCommand("inserthtml", createTable(opt, tdWidth));
    }
  };
  UE.commands["insertparagraphbeforetable"] = {
    queryCommandState: function() {
      return getTableItemsByRange(this).cell ? 0 : -1;
    },
    execCommand: function() {
      var table = getTableItemsByRange(this).table;
      if (table) {
        var p = this.document.createElement("p");
        p.innerHTML = browser.ie ? " " : "" +
              table.innerHTML
                .replace(/>\s*<")
                .replace(/\bth\b/gi, "td") +
              "
"
          );
        }
        me.fireEvent("contentchange");
        me.fireEvent("saveScene");
        html.html = "";
        return true;
      } else {
        var div = me.document.createElement("div"),
          tables;
        div.innerHTML = html.html;
        tables = div.getElementsByTagName("table");
        if (domUtils.findParentByTagName(me.selection.getStart(), "table")) {
          utils.each(tables, function(t) {
            domUtils.remove(t);
          });
          if (
            domUtils.findParentByTagName(
              me.selection.getStart(),
              "caption",
              true
            )
          ) {
            div.innerHTML = div[browser.ie ? "innerText" : "textContent"];
          }
        } else {
          utils.each(tables, function(table) {
            removeStyleSize(table, true);
            domUtils.removeAttributes(table, ["style", "border"]);
            utils.each(domUtils.getElementsByTagName(table, "td"), function(
              td
            ) {
              if (isEmptyBlock(td)) {
                domUtils.fillNode(me.document, td);
              }
              removeStyleSize(td, true);
              //                            domUtils.removeAttributes(td, ['style'])
            });
          });
        }
        html.html = div.innerHTML;
      }
    });
    me.addListener("afterpaste", function() {
      utils.each(domUtils.getElementsByTagName(me.body, "table"), function(
        table
      ) {
        if (table.offsetWidth > me.body.offsetWidth) {
          var defaultValue = getDefaultValue(me, table);
          table.style.width =
            me.body.offsetWidth -
            (needIEHack
              ? parseInt(
                  domUtils.getComputedStyle(me.body, "margin-left"),
                  10
                ) * 2
              : 0) -
            defaultValue.tableBorder * 2 -
            (me.options.offsetWidth || 0) +
            "px";
        }
      });
    });
    me.addListener("blur", function() {
      tableCopyList = null;
    });
    var timer;
    me.addListener("keydown", function() {
      clearTimeout(timer);
      timer = setTimeout(function() {
        var rng = me.selection.getRange(),
          cell = domUtils.findParentByTagName(
            rng.startContainer,
            ["th", "td"],
            true
          );
        if (cell) {
          var table = cell.parentNode.parentNode.parentNode;
          if (table.offsetWidth > table.getAttribute("width")) {
            cell.style.wordBreak = "break-all";
          }
        }
      }, 100);
    });
    me.addListener("selectionchange", function() {
      toggleDraggableState(me, false, "", null);
    });
    //内容变化时触发索引更新
    //todo 可否考虑标记检测,如果不涉及表格的变化就不进行索引重建和更新
    me.addListener("contentchange", function() {
      var me = this;
      //尽可能排除一些不需要更新的状况
      hideDragLine(me);
      if (getUETableBySelected(me)) return;
      var rng = me.selection.getRange();
      var start = rng.startContainer;
      start = domUtils.findParentByTagName(start, ["td", "th"], true);
      utils.each(domUtils.getElementsByTagName(me.document, "table"), function(
        table
      ) {
        if (me.fireEvent("excludetable", table) === true) return;
        table.ueTable = new UT(table);
        //trace:3742
        //                utils.each(domUtils.getElementsByTagName(me.document, 'td'), function (td) {
        //
        //                    if (domUtils.isEmptyBlock(td) && td !== start) {
        //                        domUtils.fillNode(me.document, td);
        //                        if (browser.ie && browser.version == 6) {
        //                            td.innerHTML = ' '
        //                        }
        //                    }
        //                });
        //                utils.each(domUtils.getElementsByTagName(me.document, 'th'), function (th) {
        //                    if (domUtils.isEmptyBlock(th) && th !== start) {
        //                        domUtils.fillNode(me.document, th);
        //                        if (browser.ie && browser.version == 6) {
        //                            th.innerHTML = ' '
        //                        }
        //                    }
        //                });
        table.onmouseover = function() {
          me.fireEvent("tablemouseover", table);
        };
        table.onmousemove = function() {
          me.fireEvent("tablemousemove", table);
          me.options.tableDragable && toggleDragButton(true, this, me);
          utils.defer(function() {
            me.fireEvent("contentchange", 50);
          }, true);
        };
        table.onmouseout = function() {
          me.fireEvent("tablemouseout", table);
          toggleDraggableState(me, false, "", null);
          hideDragLine(me);
        };
        table.onclick = function(evt) {
          evt = me.window.event || evt;
          var target = getParentTdOrTh(evt.target || evt.srcElement);
          if (!target) return;
          var ut = getUETable(target),
            table = ut.table,
            cellInfo = ut.getCellInfo(target),
            cellsRange,
            rng = me.selection.getRange();
          //                    if ("topLeft" == inPosition(table, mouseCoords(evt))) {
          //                        cellsRange = ut.getCellsRange(ut.table.rows[0].cells[0], ut.getLastCell());
          //                        ut.setSelected(cellsRange);
          //                        return;
          //                    }
          //                    if ("bottomRight" == inPosition(table, mouseCoords(evt))) {
          //
          //                        return;
          //                    }
          if (inTableSide(table, target, evt, true)) {
            var endTdCol = ut.getCell(
              ut.indexTable[ut.rowsNum - 1][cellInfo.colIndex].rowIndex,
              ut.indexTable[ut.rowsNum - 1][cellInfo.colIndex].cellIndex
            );
            if (evt.shiftKey && ut.selectedTds.length) {
              if (ut.selectedTds[0] !== endTdCol) {
                cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdCol);
                ut.setSelected(cellsRange);
              } else {
                rng && rng.selectNodeContents(endTdCol).select();
              }
            } else {
              if (target !== endTdCol) {
                cellsRange = ut.getCellsRange(target, endTdCol);
                ut.setSelected(cellsRange);
              } else {
                rng && rng.selectNodeContents(endTdCol).select();
              }
            }
            return;
          }
          if (inTableSide(table, target, evt)) {
            var endTdRow = ut.getCell(
              ut.indexTable[cellInfo.rowIndex][ut.colsNum - 1].rowIndex,
              ut.indexTable[cellInfo.rowIndex][ut.colsNum - 1].cellIndex
            );
            if (evt.shiftKey && ut.selectedTds.length) {
              if (ut.selectedTds[0] !== endTdRow) {
                cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdRow);
                ut.setSelected(cellsRange);
              } else {
                rng && rng.selectNodeContents(endTdRow).select();
              }
            } else {
              if (target !== endTdRow) {
                cellsRange = ut.getCellsRange(target, endTdRow);
                ut.setSelected(cellsRange);
              } else {
                rng && rng.selectNodeContents(endTdRow).select();
              }
            }
          }
        };
      });
      switchBorderColor(me, true);
    });
    domUtils.on(me.document, "mousemove", mouseMoveEvent);
    domUtils.on(me.document, "mouseout", function(evt) {
      var target = evt.target || evt.srcElement;
      if (target.tagName == "TABLE") {
        toggleDraggableState(me, false, "", null);
      }
    });
    /**
         * 表格隔行变色
         */
    me.addListener("interlacetable", function(type, table, classList) {
      if (!table) return;
      var me = this,
        rows = table.rows,
        len = rows.length,
        getClass = function(list, index, repeat) {
          return list[index]
            ? list[index]
            : repeat ? list[index % list.length] : "";
        };
      for (var i = 0; i < len; i++) {
        rows[i].className = getClass(
          classList || me.options.classList,
          i,
          true
        );
      }
    });
    me.addListener("uninterlacetable", function(type, table) {
      if (!table) return;
      var me = this,
        rows = table.rows,
        classList = me.options.classList,
        len = rows.length;
      for (var i = 0; i < len; i++) {
        domUtils.removeClasses(rows[i], classList);
      }
    });
    me.addListener("mousedown", mouseDownEvent);
    me.addListener("mouseup", mouseUpEvent);
    //拖动的时候触发mouseup
    domUtils.on(me.body, "dragstart", function(evt) {
      mouseUpEvent.call(me, "dragstart", evt);
    });
    me.addOutputRule(function(root) {
      utils.each(root.getNodesByTagName("div"), function(n) {
        if (n.getAttr("id") == "ue_tableDragLine") {
          n.parentNode.removeChild(n);
        }
      });
    });
    var currentRowIndex = 0;
    me.addListener("mousedown", function() {
      currentRowIndex = 0;
    });
    me.addListener("tabkeydown", function() {
      var range = this.selection.getRange(),
        common = range.getCommonAncestor(true, true),
        table = domUtils.findParentByTagName(common, "table");
      if (table) {
        if (domUtils.findParentByTagName(common, "caption", true)) {
          var cell = domUtils.getElementsByTagName(table, "th td");
          if (cell && cell.length) {
            range.setStart(cell[0], 0).setCursor(false, true);
          }
        } else {
          var cell = domUtils.findParentByTagName(common, ["td", "th"], true),
            ua = getUETable(cell);
          currentRowIndex = cell.rowSpan > 1
            ? currentRowIndex
            : ua.getCellInfo(cell).rowIndex;
          var nextCell = ua.getTabNextCell(cell, currentRowIndex);
          if (nextCell) {
            if (isEmptyBlock(nextCell)) {
              range.setStart(nextCell, 0).setCursor(false, true);
            } else {
              range.selectNodeContents(nextCell).select();
            }
          } else {
            me.fireEvent("saveScene");
            me.__hasEnterExecCommand = true;
            this.execCommand("insertrownext");
            me.__hasEnterExecCommand = false;
            range = this.selection.getRange();
            range
              .setStart(table.rows[table.rows.length - 1].cells[0], 0)
              .setCursor();
            me.fireEvent("saveScene");
          }
        }
        return true;
      }
    });
    browser.ie &&
      me.addListener("selectionchange", function() {
        toggleDraggableState(this, false, "", null);
      });
    me.addListener("keydown", function(type, evt) {
      var me = this;
      //处理在表格的最后一个输入tab产生新的表格
      var keyCode = evt.keyCode || evt.which;
      if (keyCode == 8 || keyCode == 46) {
        return;
      }
      var notCtrlKey =
        !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey;
      notCtrlKey &&
        removeSelectedClass(domUtils.getElementsByTagName(me.body, "td"));
      var ut = getUETableBySelected(me);
      if (!ut) return;
      notCtrlKey && ut.clearSelected();
    });
    me.addListener("beforegetcontent", function() {
      switchBorderColor(this, false);
      browser.ie &&
        utils.each(this.document.getElementsByTagName("caption"), function(ci) {
          if (domUtils.isEmptyNode(ci)) {
            ci.innerHTML = " ";
          }
        });
    });
    me.addListener("aftergetcontent", function() {
      switchBorderColor(this, true);
    });
    me.addListener("getAllHtml", function() {
      removeSelectedClass(me.document.getElementsByTagName("td"));
    });
    //修正全屏状态下插入的表格宽度在非全屏状态下撑开编辑器的情况
    me.addListener("fullscreenchanged", function(type, fullscreen) {
      if (!fullscreen) {
        var ratio = this.body.offsetWidth / document.body.offsetWidth,
          tables = domUtils.getElementsByTagName(this.body, "table");
        utils.each(tables, function(table) {
          if (table.offsetWidth < me.body.offsetWidth) return false;
          var tds = domUtils.getElementsByTagName(table, "td"),
            backWidths = [];
          utils.each(tds, function(td) {
            backWidths.push(td.offsetWidth);
          });
          for (var i = 0, td; (td = tds[i]); i++) {
            td.setAttribute("width", Math.floor(backWidths[i] * ratio));
          }
          table.setAttribute(
            "width",
            Math.floor(getTableWidth(me, needIEHack, getDefaultValue(me)))
          );
        });
      }
    });
    //重写execCommand命令,用于处理框选时的处理
    var oldExecCommand = me.execCommand;
    me.execCommand = function(cmd, datatat) {
      var me = this,
        args = arguments;
      cmd = cmd.toLowerCase();
      var ut = getUETableBySelected(me),
        tds,
        range = new dom.Range(me.document),
        cmdFun = me.commands[cmd] || UE.commands[cmd],
        result;
      if (!cmdFun) return;
      if (
        ut &&
        !commands[cmd] &&
        !cmdFun.notNeedUndo &&
        !me.__hasEnterExecCommand
      ) {
        me.__hasEnterExecCommand = true;
        me.fireEvent("beforeexeccommand", cmd);
        tds = ut.selectedTds;
        var lastState = -2,
          lastValue = -2,
          value,
          state;
        for (var i = 0, td; (td = tds[i]); i++) {
          if (isEmptyBlock(td)) {
            range.setStart(td, 0).setCursor(false, true);
          } else {
            range.selectNode(td).select(true);
          }
          state = me.queryCommandState(cmd);
          value = me.queryCommandValue(cmd);
          if (state != -1) {
            if (lastState !== state || lastValue !== value) {
              me._ignoreContentChange = true;
              result = oldExecCommand.apply(me, arguments);
              me._ignoreContentChange = false;
            }
            lastState = me.queryCommandState(cmd);
            lastValue = me.queryCommandValue(cmd);
            if (domUtils.isEmptyBlock(td)) {
              domUtils.fillNode(me.document, td);
            }
          }
        }
        range.setStart(tds[0], 0).shrinkBoundary(true).setCursor(false, true);
        me.fireEvent("contentchange");
        me.fireEvent("afterexeccommand", cmd);
        me.__hasEnterExecCommand = false;
        me._selectionChange();
      } else {
        result = oldExecCommand.apply(me, arguments);
      }
      return result;
    };
  });
  /**
     * 删除obj的宽高style,改成属性宽高
     * @param obj
     * @param replaceToProperty
     */
  function removeStyleSize(obj, replaceToProperty) {
    removeStyle(obj, "width", true);
    removeStyle(obj, "height", true);
  }
  function removeStyle(obj, styleName, replaceToProperty) {
    if (obj.style[styleName]) {
      replaceToProperty &&
        obj.setAttribute(styleName, parseInt(obj.style[styleName], 10));
      obj.style[styleName] = "";
    }
  }
  function getParentTdOrTh(ele) {
    if (ele.tagName == "TD" || ele.tagName == "TH") return ele;
    var td;
    if (
      (td =
        domUtils.findParentByTagName(ele, "td", true) ||
        domUtils.findParentByTagName(ele, "th", true))
    )
      return td;
    return null;
  }
  function isEmptyBlock(node) {
    var reg = new RegExp(domUtils.fillChar, "g");
    if (
      node[browser.ie ? "innerText" : "textContent"]
        .replace(/^\s*$/, "")
        .replace(reg, "").length > 0
    ) {
      return 0;
    }
    for (var n in dtd.$isNotEmpty) {
      if (node.getElementsByTagName(n).length) {
        return 0;
      }
    }
    return 1;
  }
  function mouseCoords(evt) {
    if (evt.pageX || evt.pageY) {
      return { x: evt.pageX, y: evt.pageY };
    }
    return {
      x:
        evt.clientX + me.document.body.scrollLeft - me.document.body.clientLeft,
      y: evt.clientY + me.document.body.scrollTop - me.document.body.clientTop
    };
  }
  function mouseMoveEvent(evt) {
    if (isEditorDisabled()) {
      return;
    }
    try {
      //普通状态下鼠标移动
      var target = getParentTdOrTh(evt.target || evt.srcElement),
        pos;
      //区分用户的行为是拖动还是双击
      if (isInResizeBuffer) {
        me.body.style.webkitUserSelect = "none";
        if (
          Math.abs(userActionStatus.x - evt.clientX) > offsetOfTableCell ||
          Math.abs(userActionStatus.y - evt.clientY) > offsetOfTableCell
        ) {
          clearTableDragTimer();
          isInResizeBuffer = false;
          singleClickState = 0;
          //drag action
          tableBorderDrag(evt);
        }
      }
      //修改单元格大小时的鼠标移动
      if (onDrag && dragTd) {
        singleClickState = 0;
        me.body.style.webkitUserSelect = "none";
        me.selection.getNative()[
          browser.ie9below ? "empty" : "removeAllRanges"
        ]();
        pos = mouseCoords(evt);
        toggleDraggableState(me, true, onDrag, pos, target);
        if (onDrag == "h") {
          dragLine.style.left = getPermissionX(dragTd, evt) + "px";
        } else if (onDrag == "v") {
          dragLine.style.top = getPermissionY(dragTd, evt) + "px";
        }
        return;
      }
      //当鼠标处于table上时,修改移动过程中的光标状态
      if (target) {
        //针对使用table作为容器的组件不触发拖拽效果
        if (me.fireEvent("excludetable", target) === true) return;
        pos = mouseCoords(evt);
        var state = getRelation(target, pos),
          table = domUtils.findParentByTagName(target, "table", true);
        if (inTableSide(table, target, evt, true)) {
          if (me.fireEvent("excludetable", table) === true) return;
          me.body.style.cursor =
            "url(" + me.options.cursorpath + "h.png),pointer";
        } else if (inTableSide(table, target, evt)) {
          if (me.fireEvent("excludetable", table) === true) return;
          me.body.style.cursor =
            "url(" + me.options.cursorpath + "v.png),pointer";
        } else {
          me.body.style.cursor = "text";
          var curCell = target;
          if (/\d/.test(state)) {
            state = state.replace(/\d/, "");
            target = getUETable(target).getPreviewCell(target, state == "v");
          }
          //位于第一行的顶部或者第一列的左边时不可拖动
          toggleDraggableState(
            me,
            target ? !!state : false,
            target ? state : "",
            pos,
            target
          );
        }
      } else {
        toggleDragButton(false, table, me);
      }
    } catch (e) {
      showError(e);
    }
  }
  var dragButtonTimer;
  function toggleDragButton(show, table, editor) {
    if (!show) {
      if (dragOver) return;
      dragButtonTimer = setTimeout(function() {
        !dragOver &&
          dragButton &&
          dragButton.parentNode &&
          dragButton.parentNode.removeChild(dragButton);
      }, 2000);
    } else {
      createDragButton(table, editor);
    }
  }
  function createDragButton(table, editor) {
    var pos = domUtils.getXY(table),
      doc = table.ownerDocument;
    if (dragButton && dragButton.parentNode) return dragButton;
    dragButton = doc.createElement("div");
    dragButton.contentEditable = false;
    dragButton.innerHTML = "";
    dragButton.style.cssText =
      "width:15px;height:15px;background-image:url(" +
      editor.options.UEDITOR_HOME_URL +
      "dialogs/table/dragicon.png);position: absolute;cursor:move;top:" +
      (pos.y - 15) +
      "px;left:" +
      pos.x +
      "px;";
    domUtils.unSelectable(dragButton);
    dragButton.onmouseover = function(evt) {
      dragOver = true;
    };
    dragButton.onmouseout = function(evt) {
      dragOver = false;
    };
    domUtils.on(dragButton, "click", function(type, evt) {
      doClick(evt, this);
    });
    domUtils.on(dragButton, "dblclick", function(type, evt) {
      doDblClick(evt);
    });
    domUtils.on(dragButton, "dragstart", function(type, evt) {
      domUtils.preventDefault(evt);
    });
    var timer;
    function doClick(evt, button) {
      // 部分浏览器下需要清理
      clearTimeout(timer);
      timer = setTimeout(function() {
        editor.fireEvent("tableClicked", table, button);
      }, 300);
    }
    function doDblClick(evt) {
      clearTimeout(timer);
      var ut = getUETable(table),
        start = table.rows[0].cells[0],
        end = ut.getLastCell(),
        range = ut.getCellsRange(start, end);
      editor.selection.getRange().setStart(start, 0).setCursor(false, true);
      ut.setSelected(range);
    }
    doc.body.appendChild(dragButton);
  }
  //    function inPosition(table, pos) {
  //        var tablePos = domUtils.getXY(table),
  //            width = table.offsetWidth,
  //            height = table.offsetHeight;
  //        if (pos.x - tablePos.x < 5 && pos.y - tablePos.y < 5) {
  //            return "topLeft";
  //        } else if (tablePos.x + width - pos.x < 5 && tablePos.y + height - pos.y < 5) {
  //            return "bottomRight";
  //        }
  //    }
  function inTableSide(table, cell, evt, top) {
    var pos = mouseCoords(evt),
      state = getRelation(cell, pos);
    if (top) {
      var caption = table.getElementsByTagName("caption")[0],
        capHeight = caption ? caption.offsetHeight : 0;
      return state == "v1" && pos.y - domUtils.getXY(table).y - capHeight < 8;
    } else {
      return state == "h1" && pos.x - domUtils.getXY(table).x < 8;
    }
  }
  /**
     * 获取拖动时允许的X轴坐标
     * @param dragTd
     * @param evt
     */
  function getPermissionX(dragTd, evt) {
    var ut = getUETable(dragTd);
    if (ut) {
      var preTd = ut.getSameEndPosCells(dragTd, "x")[0],
        nextTd = ut.getSameStartPosXCells(dragTd)[0],
        mouseX = mouseCoords(evt).x,
        left =
          (preTd ? domUtils.getXY(preTd).x : domUtils.getXY(ut.table).x) + 20,
        right = nextTd
          ? domUtils.getXY(nextTd).x + nextTd.offsetWidth - 20
          : me.body.offsetWidth + 5 ||
              parseInt(domUtils.getComputedStyle(me.body, "width"), 10);
      left += cellMinWidth;
      right -= cellMinWidth;
      return mouseX < left ? left : mouseX > right ? right : mouseX;
    }
  }
  /**
     * 获取拖动时允许的Y轴坐标
     */
  function getPermissionY(dragTd, evt) {
    try {
      var top = domUtils.getXY(dragTd).y,
        mousePosY = mouseCoords(evt).y;
      return mousePosY < top ? top : mousePosY;
    } catch (e) {
      showError(e);
    }
  }
  /**
     * 移动状态切换
     */
  function toggleDraggableState(editor, draggable, dir, mousePos, cell) {
    try {
      editor.body.style.cursor = dir == "h"
        ? "col-resize"
        : dir == "v" ? "row-resize" : "text";
      if (browser.ie) {
        if (dir && !mousedown && !getUETableBySelected(editor)) {
          getDragLine(editor, editor.document);
          showDragLineAt(dir, cell);
        } else {
          hideDragLine(editor);
        }
      }
      onBorder = draggable;
    } catch (e) {
      showError(e);
    }
  }
  /**
     * 获取与UETable相关的resize line
     * @param uetable UETable对象
     */
  function getResizeLineByUETable() {
    var lineId = "_UETableResizeLine",
      line = this.document.getElementById(lineId);
    if (!line) {
      line = this.document.createElement("div");
      line.id = lineId;
      line.contnetEditable = false;
      line.setAttribute("unselectable", "on");
      var styles = {
        width: 2 * cellBorderWidth + 1 + "px",
        position: "absolute",
        "z-index": 100000,
        cursor: "col-resize",
        background: "red",
        display: "none"
      };
      //切换状态
      line.onmouseout = function() {
        this.style.display = "none";
      };
      utils.extend(line.style, styles);
      this.document.body.appendChild(line);
    }
    return line;
  }
  /**
     * 更新resize-line
     */
  function updateResizeLine(cell, uetable) {
    var line = getResizeLineByUETable.call(this),
      table = uetable.table,
      styles = {
        top: domUtils.getXY(table).y + "px",
        left:
          domUtils.getXY(cell).x + cell.offsetWidth - cellBorderWidth + "px",
        display: "block",
        height: table.offsetHeight + "px"
      };
    utils.extend(line.style, styles);
  }
  /**
     * 显示resize-line
     */
  function showResizeLine(cell) {
    var uetable = getUETable(cell);
    updateResizeLine.call(this, cell, uetable);
  }
  /**
     * 获取鼠标与当前单元格的相对位置
     * @param ele
     * @param mousePos
     */
  function getRelation(ele, mousePos) {
    var elePos = domUtils.getXY(ele);
    if (!elePos) {
      return "";
    }
    if (elePos.x + ele.offsetWidth - mousePos.x < cellBorderWidth) {
      return "h";
    }
    if (mousePos.x - elePos.x < cellBorderWidth) {
      return "h1";
    }
    if (elePos.y + ele.offsetHeight - mousePos.y < cellBorderWidth) {
      return "v";
    }
    if (mousePos.y - elePos.y < cellBorderWidth) {
      return "v1";
    }
    return "";
  }
  function mouseDownEvent(type, evt) {
    if (isEditorDisabled()) {
      return;
    }
    userActionStatus = {
      x: evt.clientX,
      y: evt.clientY
    };
    //右键菜单单独处理
    if (evt.button == 2) {
      var ut = getUETableBySelected(me),
        flag = false;
      if (ut) {
        var td = getTargetTd(me, evt);
        utils.each(ut.selectedTds, function(ti) {
          if (ti === td) {
            flag = true;
          }
        });
        if (!flag) {
          removeSelectedClass(domUtils.getElementsByTagName(me.body, "th td"));
          ut.clearSelected();
        } else {
          td = ut.selectedTds[0];
          setTimeout(function() {
            me.selection.getRange().setStart(td, 0).setCursor(false, true);
          }, 0);
        }
      }
    } else {
      tableClickHander(evt);
    }
  }
  //清除表格的计时器
  function clearTableTimer() {
    tabTimer && clearTimeout(tabTimer);
    tabTimer = null;
  }
  //双击收缩
  function tableDbclickHandler(evt) {
    singleClickState = 0;
    evt = evt || me.window.event;
    var target = getParentTdOrTh(evt.target || evt.srcElement);
    if (target) {
      var h;
      if ((h = getRelation(target, mouseCoords(evt)))) {
        hideDragLine(me);
        if (h == "h1") {
          h = "h";
          if (
            inTableSide(
              domUtils.findParentByTagName(target, "table"),
              target,
              evt
            )
          ) {
            me.execCommand("adaptbywindow");
          } else {
            target = getUETable(target).getPreviewCell(target);
            if (target) {
              var rng = me.selection.getRange();
              rng.selectNodeContents(target).setCursor(true, true);
            }
          }
        }
        if (h == "h") {
          var ut = getUETable(target),
            table = ut.table,
            cells = getCellsByMoveBorder(target, table, true);
          cells = extractArray(cells, "left");
          ut.width = ut.offsetWidth;
          var oldWidth = [],
            newWidth = [];
          utils.each(cells, function(cell) {
            oldWidth.push(cell.offsetWidth);
          });
          utils.each(cells, function(cell) {
            cell.removeAttribute("width");
          });
          window.setTimeout(function() {
            //是否允许改变
            var changeable = true;
            utils.each(cells, function(cell, index) {
              var width = cell.offsetWidth;
              if (width > oldWidth[index]) {
                changeable = false;
                return false;
              }
              newWidth.push(width);
            });
            var change = changeable ? newWidth : oldWidth;
            utils.each(cells, function(cell, index) {
              cell.width = change[index] - getTabcellSpace();
            });
          }, 0);
          //                    minWidth -= cellMinWidth;
          //
          //                    table.removeAttribute("width");
          //                    utils.each(cells, function (cell) {
          //                        cell.style.width = "";
          //                        cell.width -= minWidth;
          //                    });
        }
      }
    }
  }
  function tableClickHander(evt) {
    removeSelectedClass(domUtils.getElementsByTagName(me.body, "td th"));
    //trace:3113
    //选中单元格,点击table外部,不会清掉table上挂的ueTable,会引起getUETableBySelected方法返回值
    utils.each(me.document.getElementsByTagName("table"), function(t) {
      t.ueTable = null;
    });
    startTd = getTargetTd(me, evt);
    if (!startTd) return;
    var table = domUtils.findParentByTagName(startTd, "table", true);
    ut = getUETable(table);
    ut && ut.clearSelected();
    //判断当前鼠标状态
    if (!onBorder) {
      me.document.body.style.webkitUserSelect = "";
      mousedown = true;
      me.addListener("mouseover", mouseOverEvent);
    } else {
      //边框上的动作处理
      borderActionHandler(evt);
    }
  }
  //处理表格边框上的动作, 这里做延时处理,避免两种动作互相影响
  function borderActionHandler(evt) {
    if (browser.ie) {
      evt = reconstruct(evt);
    }
    clearTableDragTimer();
    //是否正在等待resize的缓冲中
    isInResizeBuffer = true;
    tableDragTimer = setTimeout(function() {
      tableBorderDrag(evt);
    }, dblclickTime);
  }
  function extractArray(originArr, key) {
    var result = [],
      tmp = null;
    for (var i = 0, len = originArr.length; i < len; i++) {
      tmp = originArr[i][key];
      if (tmp) {
        result.push(tmp);
      }
    }
    return result;
  }
  function clearTableDragTimer() {
    tableDragTimer && clearTimeout(tableDragTimer);
    tableDragTimer = null;
  }
  function reconstruct(obj) {
    var attrs = [
      "pageX",
      "pageY",
      "clientX",
      "clientY",
      "srcElement",
      "target"
    ],
      newObj = {};
    if (obj) {
      for (var i = 0, key, val; (key = attrs[i]); i++) {
        val = obj[key];
        val && (newObj[key] = val);
      }
    }
    return newObj;
  }
  //边框拖动
  function tableBorderDrag(evt) {
    isInResizeBuffer = false;
    startTd = evt.target || evt.srcElement;
    if (!startTd) return;
    var state = getRelation(startTd, mouseCoords(evt));
    if (/\d/.test(state)) {
      state = state.replace(/\d/, "");
      startTd = getUETable(startTd).getPreviewCell(startTd, state == "v");
    }
    hideDragLine(me);
    getDragLine(me, me.document);
    me.fireEvent("saveScene");
    showDragLineAt(state, startTd);
    mousedown = true;
    //拖动开始
    onDrag = state;
    dragTd = startTd;
  }
  function mouseUpEvent(type, evt) {
    if (isEditorDisabled()) {
      return;
    }
    clearTableDragTimer();
    isInResizeBuffer = false;
    if (onBorder) {
      singleClickState = ++singleClickState % 3;
      userActionStatus = {
        x: evt.clientX,
        y: evt.clientY
      };
      tableResizeTimer = setTimeout(function() {
        singleClickState > 0 && singleClickState--;
      }, dblclickTime);
      if (singleClickState === 2) {
        singleClickState = 0;
        tableDbclickHandler(evt);
        return;
      }
    }
    if (evt.button == 2) return;
    var me = this;
    //清除表格上原生跨选问题
    var range = me.selection.getRange(),
      start = domUtils.findParentByTagName(range.startContainer, "table", true),
      end = domUtils.findParentByTagName(range.endContainer, "table", true);
    if (start || end) {
      if (start === end) {
        start = domUtils.findParentByTagName(
          range.startContainer,
          ["td", "th", "caption"],
          true
        );
        end = domUtils.findParentByTagName(
          range.endContainer,
          ["td", "th", "caption"],
          true
        );
        if (start !== end) {
          me.selection.clearRange();
        }
      } else {
        me.selection.clearRange();
      }
    }
    mousedown = false;
    me.document.body.style.webkitUserSelect = "";
    //拖拽状态下的mouseUP
    if (onDrag && dragTd) {
      me.selection.getNative()[
        browser.ie9below ? "empty" : "removeAllRanges"
      ]();
      singleClickState = 0;
      dragLine = me.document.getElementById("ue_tableDragLine");
      // trace 3973
      if (dragLine) {
        var dragTdPos = domUtils.getXY(dragTd),
          dragLinePos = domUtils.getXY(dragLine);
        switch (onDrag) {
          case "h":
            changeColWidth(dragTd, dragLinePos.x - dragTdPos.x);
            break;
          case "v":
            changeRowHeight(
              dragTd,
              dragLinePos.y - dragTdPos.y - dragTd.offsetHeight
            );
            break;
          default:
        }
        onDrag = "";
        dragTd = null;
        hideDragLine(me);
        me.fireEvent("saveScene");
        return;
      }
    }
    //正常状态下的mouseup
    if (!startTd) {
      var target = domUtils.findParentByTagName(
        evt.target || evt.srcElement,
        "td",
        true
      );
      if (!target)
        target = domUtils.findParentByTagName(
          evt.target || evt.srcElement,
          "th",
          true
        );
      if (target && (target.tagName == "TD" || target.tagName == "TH")) {
        if (me.fireEvent("excludetable", target) === true) return;
        range = new dom.Range(me.document);
        range.setStart(target, 0).setCursor(false, true);
      }
    } else {
      var ut = getUETable(startTd),
        cell = ut ? ut.selectedTds[0] : null;
      if (cell) {
        range = new dom.Range(me.document);
        if (domUtils.isEmptyBlock(cell)) {
          range.setStart(cell, 0).setCursor(false, true);
        } else {
          range
            .selectNodeContents(cell)
            .shrinkBoundary()
            .setCursor(false, true);
        }
      } else {
        range = me.selection.getRange().shrinkBoundary();
        if (!range.collapsed) {
          var start = domUtils.findParentByTagName(
            range.startContainer,
            ["td", "th"],
            true
          ),
            end = domUtils.findParentByTagName(
              range.endContainer,
              ["td", "th"],
              true
            );
          //在table里边的不能清除
          if (
            (start && !end) ||
            (!start && end) ||
            (start && end && start !== end)
          ) {
            range.setCursor(false, true);
          }
        }
      }
      startTd = null;
      me.removeListener("mouseover", mouseOverEvent);
    }
    me._selectionChange(250, evt);
  }
  function mouseOverEvent(type, evt) {
    if (isEditorDisabled()) {
      return;
    }
    var me = this,
      tar = evt.target || evt.srcElement;
    currentTd =
      domUtils.findParentByTagName(tar, "td", true) ||
      domUtils.findParentByTagName(tar, "th", true);
    //需要判断两个TD是否位于同一个表格内
    if (
      startTd &&
      currentTd &&
      ((startTd.tagName == "TD" && currentTd.tagName == "TD") ||
        (startTd.tagName == "TH" && currentTd.tagName == "TH")) &&
      domUtils.findParentByTagName(startTd, "table") ==
        domUtils.findParentByTagName(currentTd, "table")
    ) {
      var ut = getUETable(currentTd);
      if (startTd != currentTd) {
        me.document.body.style.webkitUserSelect = "none";
        me.selection.getNative()[
          browser.ie9below ? "empty" : "removeAllRanges"
        ]();
        var range = ut.getCellsRange(startTd, currentTd);
        ut.setSelected(range);
      } else {
        me.document.body.style.webkitUserSelect = "";
        ut.clearSelected();
      }
    }
    evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
  }
  function setCellHeight(cell, height, backHeight) {
    var lineHight = parseInt(
      domUtils.getComputedStyle(cell, "line-height"),
      10
    ),
      tmpHeight = backHeight + height;
    height = tmpHeight < lineHight ? lineHight : tmpHeight;
    if (cell.style.height) cell.style.height = "";
    cell.rowSpan == 1
      ? cell.setAttribute("height", height)
      : cell.removeAttribute && cell.removeAttribute("height");
  }
  function getWidth(cell) {
    if (!cell) return 0;
    return parseInt(domUtils.getComputedStyle(cell, "width"), 10);
  }
  function changeColWidth(cell, changeValue) {
    var ut = getUETable(cell);
    if (ut) {
      //根据当前移动的边框获取相关的单元格
      var table = ut.table,
        cells = getCellsByMoveBorder(cell, table);
      table.style.width = "";
      table.removeAttribute("width");
      //修正改变量
      changeValue = correctChangeValue(changeValue, cell, cells);
      if (cell.nextSibling) {
        var i = 0;
        utils.each(cells, function(cellGroup) {
          cellGroup.left.width = +cellGroup.left.width + changeValue;
          cellGroup.right &&
            (cellGroup.right.width = +cellGroup.right.width - changeValue);
        });
      } else {
        utils.each(cells, function(cellGroup) {
          cellGroup.left.width -= -changeValue;
        });
      }
    }
  }
  function isEditorDisabled() {
    return me.body.contentEditable === "false";
  }
  function changeRowHeight(td, changeValue) {
    if (Math.abs(changeValue) < 10) return;
    var ut = getUETable(td);
    if (ut) {
      var cells = ut.getSameEndPosCells(td, "y"),
        //备份需要连带变化的td的原始高度,否则后期无法获取正确的值
        backHeight = cells[0] ? cells[0].offsetHeight : 0;
      for (var i = 0, cell; (cell = cells[i++]); ) {
        setCellHeight(cell, changeValue, backHeight);
      }
    }
  }
  /**
     * 获取调整单元格大小的相关单元格
     * @isContainMergeCell 返回的结果中是否包含发生合并后的单元格
     */
  function getCellsByMoveBorder(cell, table, isContainMergeCell) {
    if (!table) {
      table = domUtils.findParentByTagName(cell, "table");
    }
    if (!table) {
      return null;
    }
    //获取到该单元格所在行的序列号
    var index = domUtils.getNodeIndex(cell),
      temp = cell,
      rows = table.rows,
      colIndex = 0;
    while (temp) {
      //获取到当前单元格在未发生单元格合并时的序列
      if (temp.nodeType === 1) {
        colIndex += temp.colSpan || 1;
      }
      temp = temp.previousSibling;
    }
    temp = null;
    //记录想关的单元格
    var borderCells = [];
    utils.each(rows, function(tabRow) {
      var cells = tabRow.cells,
        currIndex = 0;
      utils.each(cells, function(tabCell) {
        currIndex += tabCell.colSpan || 1;
        if (currIndex === colIndex) {
          borderCells.push({
            left: tabCell,
            right: tabCell.nextSibling || null
          });
          return false;
        } else if (currIndex > colIndex) {
          if (isContainMergeCell) {
            borderCells.push({
              left: tabCell
            });
          }
          return false;
        }
      });
    });
    return borderCells;
  }
  /**
     * 通过给定的单元格集合获取最小的单元格width
     */
  function getMinWidthByTableCells(cells) {
    var minWidth = Number.MAX_VALUE;
    for (var i = 0, curCell; (curCell = cells[i]); i++) {
      minWidth = Math.min(
        minWidth,
        curCell.width || getTableCellWidth(curCell)
      );
    }
    return minWidth;
  }
  function correctChangeValue(changeValue, relatedCell, cells) {
    //为单元格的paading预留空间
    changeValue -= getTabcellSpace();
    if (changeValue < 0) {
      return 0;
    }
    changeValue -= getTableCellWidth(relatedCell);
    //确定方向
    var direction = changeValue < 0 ? "left" : "right";
    changeValue = Math.abs(changeValue);
    //只关心非最后一个单元格就可以
    utils.each(cells, function(cellGroup) {
      var curCell = cellGroup[direction];
      //为单元格保留最小空间
      if (curCell) {
        changeValue = Math.min(
          changeValue,
          getTableCellWidth(curCell) - cellMinWidth
        );
      }
    });
    //修正越界
    changeValue = changeValue < 0 ? 0 : changeValue;
    return direction === "left" ? -changeValue : changeValue;
  }
  function getTableCellWidth(cell) {
    var width = 0,
      //偏移纠正量
      offset = 0,
      width = cell.offsetWidth - getTabcellSpace();
    //最后一个节点纠正一下
    if (!cell.nextSibling) {
      width -= getTableCellOffset(cell);
    }
    width = width < 0 ? 0 : width;
    try {
      cell.width = width;
    } catch (e) {}
    return width;
  }
  /**
     * 获取单元格所在表格的最末单元格的偏移量
     */
  function getTableCellOffset(cell) {
    tab = domUtils.findParentByTagName(cell, "table", false);
    if (tab.offsetVal === undefined) {
      var prev = cell.previousSibling;
      if (prev) {
        //最后一个单元格和前一个单元格的width diff结果 如果恰好为一个border width, 则条件成立
        tab.offsetVal = cell.offsetWidth - prev.offsetWidth === UT.borderWidth
          ? UT.borderWidth
          : 0;
      } else {
        tab.offsetVal = 0;
      }
    }
    return tab.offsetVal;
  }
  function getTabcellSpace() {
    if (UT.tabcellSpace === undefined) {
      var cell = null,
        tab = me.document.createElement("table"),
        tbody = me.document.createElement("tbody"),
        trow = me.document.createElement("tr"),
        tabcell = me.document.createElement("td"),
        mirror = null;
      tabcell.style.cssText = "border: 0;";
      tabcell.width = 1;
      trow.appendChild(tabcell);
      trow.appendChild((mirror = tabcell.cloneNode(false)));
      tbody.appendChild(trow);
      tab.appendChild(tbody);
      tab.style.cssText = "visibility: hidden;";
      me.body.appendChild(tab);
      UT.paddingSpace = tabcell.offsetWidth - 1;
      var tmpTabWidth = tab.offsetWidth;
      tabcell.style.cssText = "";
      mirror.style.cssText = "";
      UT.borderWidth = (tab.offsetWidth - tmpTabWidth) / 3;
      UT.tabcellSpace = UT.paddingSpace + UT.borderWidth;
      me.body.removeChild(tab);
    }
    getTabcellSpace = function() {
      return UT.tabcellSpace;
    };
    return UT.tabcellSpace;
  }
  function getDragLine(editor, doc) {
    if (mousedown) return;
    dragLine = editor.document.createElement("div");
    domUtils.setAttributes(dragLine, {
      id: "ue_tableDragLine",
      unselectable: "on",
      contenteditable: false,
      onresizestart: "return false",
      ondragstart: "return false",
      onselectstart: "return false",
      style:
        "background-color:blue;position:absolute;padding:0;margin:0;background-image:none;border:0px none;opacity:0;filter:alpha(opacity=0)"
    });
    editor.body.appendChild(dragLine);
  }
  function hideDragLine(editor) {
    if (mousedown) return;
    var line;
    while ((line = editor.document.getElementById("ue_tableDragLine"))) {
      domUtils.remove(line);
    }
  }
  /**
     * 依据state(v|h)在cell位置显示横线
     * @param state
     * @param cell
     */
  function showDragLineAt(state, cell) {
    if (!cell) return;
    var table = domUtils.findParentByTagName(cell, "table"),
      caption = table.getElementsByTagName("caption"),
      width = table.offsetWidth,
      height =
        table.offsetHeight - (caption.length > 0 ? caption[0].offsetHeight : 0),
      tablePos = domUtils.getXY(table),
      cellPos = domUtils.getXY(cell),
      css;
    switch (state) {
      case "h":
        css =
          "height:" +
          height +
          "px;top:" +
          (tablePos.y + (caption.length > 0 ? caption[0].offsetHeight : 0)) +
          "px;left:" +
          (cellPos.x + cell.offsetWidth);
        dragLine.style.cssText =
          css +
          "px;position: absolute;display:block;background-color:blue;width:1px;border:0; color:blue;opacity:.3;filter:alpha(opacity=30)";
        break;
      case "v":
        css =
          "width:" +
          width +
          "px;left:" +
          tablePos.x +
          "px;top:" +
          (cellPos.y + cell.offsetHeight);
        //必须加上border:0和color:blue,否则低版ie不支持背景色显示
        dragLine.style.cssText =
          css +
          "px;overflow:hidden;position: absolute;display:block;background-color:blue;height:1px;border:0;color:blue;opacity:.2;filter:alpha(opacity=20)";
        break;
      default:
    }
  }
  /**
     * 当表格边框颜色为白色时设置为虚线,true为添加虚线
     * @param editor
     * @param flag
     */
  function switchBorderColor(editor, flag) {
    var tableArr = domUtils.getElementsByTagName(editor.body, "table"),
      color;
    for (var i = 0, node; (node = tableArr[i++]); ) {
      var td = domUtils.getElementsByTagName(node, "td");
      if (td[0]) {
        if (flag) {
          color = td[0].style.borderColor.replace(/\s/g, "");
          if (/(#ffffff)|(rgb\(255,255,255\))/gi.test(color))
            domUtils.addClass(node, "noBorderTable");
        } else {
          domUtils.removeClasses(node, "noBorderTable");
        }
      }
    }
  }
  function getTableWidth(editor, needIEHack, defaultValue) {
    var body = editor.body;
    return (
      body.offsetWidth -
      (needIEHack
        ? parseInt(domUtils.getComputedStyle(body, "margin-left"), 10) * 2
        : 0) -
      defaultValue.tableBorder * 2 -
      (editor.options.offsetWidth || 0)
    );
  }
  /**
     * 获取当前拖动的单元格
     */
  function getTargetTd(editor, evt) {
    var target = domUtils.findParentByTagName(
      evt.target || evt.srcElement,
      ["td", "th"],
      true
    ),
      dir = null;
    if (!target) {
      return null;
    }
    dir = getRelation(target, mouseCoords(evt));
    //如果有前一个节点, 需要做一个修正, 否则可能会得到一个错误的td
    if (!target) {
      return null;
    }
    if (dir === "h1" && target.previousSibling) {
      var position = domUtils.getXY(target),
        cellWidth = target.offsetWidth;
      if (Math.abs(position.x + cellWidth - evt.clientX) > cellWidth / 3) {
        target = target.previousSibling;
      }
    } else if (dir === "v1" && target.parentNode.previousSibling) {
      var position = domUtils.getXY(target),
        cellHeight = target.offsetHeight;
      if (Math.abs(position.y + cellHeight - evt.clientY) > cellHeight / 3) {
        target = target.parentNode.previousSibling.firstChild;
      }
    }
    //排除了非td内部以及用于代码高亮部分的td
    return target && !(editor.fireEvent("excludetable", target) === true)
      ? target
      : null;
  }
};
// plugins/table.sort.js
/**
 * Created with JetBrains PhpStorm.
 * User: Jinqn
 * Date: 13-10-12
 * Time: 上午10:20
 * To change this template use File | Settings | File Templates.
 */
UE.UETable.prototype.sortTable = function(sortByCellIndex, compareFn) {
  var table = this.table,
    rows = table.rows,
    trArray = [],
    flag = rows[0].cells[0].tagName === "TH",
    lastRowIndex = 0;
  if (this.selectedTds.length) {
    var range = this.cellsRange,
      len = range.endRowIndex + 1;
    for (var i = range.beginRowIndex; i < len; i++) {
      trArray[i] = rows[i];
    }
    trArray.splice(0, range.beginRowIndex);
    lastRowIndex = range.endRowIndex + 1 === this.rowsNum
      ? 0
      : range.endRowIndex + 1;
  } else {
    for (var i = 0, len = rows.length; i < len; i++) {
      trArray[i] = rows[i];
    }
  }
  var Fn = {
    reversecurrent: function(td1, td2) {
      return 1;
    },
    orderbyasc: function(td1, td2) {
      var value1 = td1.innerText || td1.textContent,
        value2 = td2.innerText || td2.textContent;
      return value1.localeCompare(value2);
    },
    reversebyasc: function(td1, td2) {
      var value1 = td1.innerHTML,
        value2 = td2.innerHTML;
      return value2.localeCompare(value1);
    },
    orderbynum: function(td1, td2) {
      var value1 = td1[browser.ie ? "innerText" : "textContent"].match(/\d+/),
        value2 = td2[browser.ie ? "innerText" : "textContent"].match(/\d+/);
      if (value1) value1 = +value1[0];
      if (value2) value2 = +value2[0];
      return (value1 || 0) - (value2 || 0);
    },
    reversebynum: function(td1, td2) {
      var value1 = td1[browser.ie ? "innerText" : "textContent"].match(/\d+/),
        value2 = td2[browser.ie ? "innerText" : "textContent"].match(/\d+/);
      if (value1) value1 = +value1[0];
      if (value2) value2 = +value2[0];
      return (value2 || 0) - (value1 || 0);
    }
  };
  //对表格设置排序的标记data-sort-type
  table.setAttribute(
    "data-sort-type",
    compareFn && typeof compareFn === "string" && Fn[compareFn] ? compareFn : ""
  );
  //th不参与排序
  flag && trArray.splice(0, 1);
  trArray = utils.sort(trArray, function(tr1, tr2) {
    var result;
    if (compareFn && typeof compareFn === "function") {
      result = compareFn.call(
        this,
        tr1.cells[sortByCellIndex],
        tr2.cells[sortByCellIndex]
      );
    } else if (compareFn && typeof compareFn === "number") {
      result = 1;
    } else if (compareFn && typeof compareFn === "string" && Fn[compareFn]) {
      result = Fn[compareFn].call(
        this,
        tr1.cells[sortByCellIndex],
        tr2.cells[sortByCellIndex]
      );
    } else {
      result = Fn["orderbyasc"].call(
        this,
        tr1.cells[sortByCellIndex],
        tr2.cells[sortByCellIndex]
      );
    }
    return result;
  });
  var fragment = table.ownerDocument.createDocumentFragment();
  for (var j = 0, len = trArray.length; j < len; j++) {
    fragment.appendChild(trArray[j]);
  }
  var tbody = table.getElementsByTagName("tbody")[0];
  if (!lastRowIndex) {
    tbody.appendChild(fragment);
  } else {
    tbody.insertBefore(
      fragment,
      rows[lastRowIndex - range.endRowIndex + range.beginRowIndex - 1]
    );
  }
};
UE.plugins["tablesort"] = function() {
  var me = this,
    UT = UE.UETable,
    getUETable = function(tdOrTable) {
      return UT.getUETable(tdOrTable);
    },
    getTableItemsByRange = function(editor) {
      return UT.getTableItemsByRange(editor);
    };
  me.ready(function() {
    //添加表格可排序的样式
    utils.cssRule(
      "tablesort",
      "table.sortEnabled tr.firstRow th,table.sortEnabled tr.firstRow td{padding-right:20px;background-repeat: no-repeat;background-position: center right;" +
        "   background-image:url(" +
        me.options.themePath +
        me.options.theme +
        "/images/sortable.png);}",
      me.document
    );
    //做单元格合并操作时,清除可排序标识
    me.addListener("afterexeccommand", function(type, cmd) {
      if (cmd == "mergeright" || cmd == "mergedown" || cmd == "mergecells") {
        this.execCommand("disablesort");
      }
    });
  });
  //表格排序
  UE.commands["sorttable"] = {
    queryCommandState: function() {
      var me = this,
        tableItems = getTableItemsByRange(me);
      if (!tableItems.cell) return -1;
      var table = tableItems.table,
        cells = table.getElementsByTagName("td");
      for (var i = 0, cell; (cell = cells[i++]); ) {
        if (cell.rowSpan != 1 || cell.colSpan != 1) return -1;
      }
      return 0;
    },
    execCommand: function(cmd, fn) {
      var me = this,
        range = me.selection.getRange(),
        bk = range.createBookmark(true),
        tableItems = getTableItemsByRange(me),
        cell = tableItems.cell,
        ut = getUETable(tableItems.table),
        cellInfo = ut.getCellInfo(cell);
      ut.sortTable(cellInfo.cellIndex, fn);
      range.moveToBookmark(bk);
      try {
        range.select();
      } catch (e) {}
    }
  };
  //设置表格可排序,清除表格可排序
  UE.commands["enablesort"] = UE.commands["disablesort"] = {
    queryCommandState: function(cmd) {
      var table = getTableItemsByRange(this).table;
      if (table && cmd == "enablesort") {
        var cells = domUtils.getElementsByTagName(table, "th td");
        for (var i = 0; i < cells.length; i++) {
          if (
            cells[i].getAttribute("colspan") > 1 ||
            cells[i].getAttribute("rowspan") > 1
          )
            return -1;
        }
      }
      return !table
        ? -1
        : (cmd == "enablesort") ^
            (table.getAttribute("data-sort") != "sortEnabled")
          ? -1
          : 0;
    },
    execCommand: function(cmd) {
      var table = getTableItemsByRange(this).table;
      table.setAttribute(
        "data-sort",
        cmd == "enablesort" ? "sortEnabled" : "sortDisabled"
      );
      cmd == "enablesort"
        ? domUtils.addClass(table, "sortEnabled")
        : domUtils.removeClasses(table, "sortEnabled");
    }
  };
};
// plugins/contextmenu.js
///import core
///commands 右键菜单
///commandsName  ContextMenu
///commandsTitle  右键菜单
/**
 * 右键菜单
 * @function
 * @name baidu.editor.plugins.contextmenu
 * @author zhanyi
 */
UE.plugins["contextmenu"] = function() {
  var me = this;
  me.setOpt("enableContextMenu", me.getOpt("enableContextMenu") || true);
  if (me.getOpt("enableContextMenu") === false) {
    return;
  }
  var lang = me.getLang("contextMenu"),
    menu,
    items = me.options.contextMenu || [
      { label: lang["selectall"], cmdName: "selectall" },
      {
        label: lang.cleardoc,
        cmdName: "cleardoc",
        exec: function() {
          if (confirm(lang.confirmclear)) {
            this.execCommand("cleardoc");
          }
        }
      },
      "-",
      {
        label: lang.unlink,
        cmdName: "unlink"
      },
      "-",
      {
        group: lang.paragraph,
        icon: "justifyjustify",
        subMenu: [
          {
            label: lang.justifyleft,
            cmdName: "justify",
            value: "left"
          },
          {
            label: lang.justifyright,
            cmdName: "justify",
            value: "right"
          },
          {
            label: lang.justifycenter,
            cmdName: "justify",
            value: "center"
          },
          {
            label: lang.justifyjustify,
            cmdName: "justify",
            value: "justify"
          }
        ]
      },
      "-",
      {
        group: lang.table,
        icon: "table",
        subMenu: [
          {
            label: lang.inserttable,
            cmdName: "inserttable"
          },
          {
            label: lang.deletetable,
            cmdName: "deletetable"
          },
          "-",
          {
            label: lang.deleterow,
            cmdName: "deleterow"
          },
          {
            label: lang.deletecol,
            cmdName: "deletecol"
          },
          {
            label: lang.insertcol,
            cmdName: "insertcol"
          },
          {
            label: lang.insertcolnext,
            cmdName: "insertcolnext"
          },
          {
            label: lang.insertrow,
            cmdName: "insertrow"
          },
          {
            label: lang.insertrownext,
            cmdName: "insertrownext"
          },
          "-",
          {
            label: lang.insertcaption,
            cmdName: "insertcaption"
          },
          {
            label: lang.deletecaption,
            cmdName: "deletecaption"
          },
          {
            label: lang.inserttitle,
            cmdName: "inserttitle"
          },
          {
            label: lang.deletetitle,
            cmdName: "deletetitle"
          },
          {
            label: lang.inserttitlecol,
            cmdName: "inserttitlecol"
          },
          {
            label: lang.deletetitlecol,
            cmdName: "deletetitlecol"
          },
          "-",
          {
            label: lang.mergecells,
            cmdName: "mergecells"
          },
          {
            label: lang.mergeright,
            cmdName: "mergeright"
          },
          {
            label: lang.mergedown,
            cmdName: "mergedown"
          },
          "-",
          {
            label: lang.splittorows,
            cmdName: "splittorows"
          },
          {
            label: lang.splittocols,
            cmdName: "splittocols"
          },
          {
            label: lang.splittocells,
            cmdName: "splittocells"
          },
          "-",
          {
            label: lang.averageDiseRow,
            cmdName: "averagedistributerow"
          },
          {
            label: lang.averageDisCol,
            cmdName: "averagedistributecol"
          },
          "-",
          {
            label: lang.edittd,
            cmdName: "edittd",
            exec: function() {
              if (UE.ui["edittd"]) {
                new UE.ui["edittd"](this);
              }
              this.getDialog("edittd").open();
            }
          },
          {
            label: lang.edittable,
            cmdName: "edittable",
            exec: function() {
              if (UE.ui["edittable"]) {
                new UE.ui["edittable"](this);
              }
              this.getDialog("edittable").open();
            }
          },
          {
            label: lang.setbordervisible,
            cmdName: "setbordervisible"
          }
        ]
      },
      {
        group: lang.tablesort,
        icon: "tablesort",
        subMenu: [
          {
            label: lang.enablesort,
            cmdName: "enablesort"
          },
          {
            label: lang.disablesort,
            cmdName: "disablesort"
          },
          "-",
          {
            label: lang.reversecurrent,
            cmdName: "sorttable",
            value: "reversecurrent"
          },
          {
            label: lang.orderbyasc,
            cmdName: "sorttable",
            value: "orderbyasc"
          },
          {
            label: lang.reversebyasc,
            cmdName: "sorttable",
            value: "reversebyasc"
          },
          {
            label: lang.orderbynum,
            cmdName: "sorttable",
            value: "orderbynum"
          },
          {
            label: lang.reversebynum,
            cmdName: "sorttable",
            value: "reversebynum"
          }
        ]
      },
      {
        group: lang.borderbk,
        icon: "borderBack",
        subMenu: [
          {
            label: lang.setcolor,
            cmdName: "interlacetable",
            exec: function() {
              this.execCommand("interlacetable");
            }
          },
          {
            label: lang.unsetcolor,
            cmdName: "uninterlacetable",
            exec: function() {
              this.execCommand("uninterlacetable");
            }
          },
          {
            label: lang.setbackground,
            cmdName: "settablebackground",
            exec: function() {
              this.execCommand("settablebackground", {
                repeat: true,
                colorList: ["#bbb", "#ccc"]
              });
            }
          },
          {
            label: lang.unsetbackground,
            cmdName: "cleartablebackground",
            exec: function() {
              this.execCommand("cleartablebackground");
            }
          },
          {
            label: lang.redandblue,
            cmdName: "settablebackground",
            exec: function() {
              this.execCommand("settablebackground", {
                repeat: true,
                colorList: ["red", "blue"]
              });
            }
          },
          {
            label: lang.threecolorgradient,
            cmdName: "settablebackground",
            exec: function() {
              this.execCommand("settablebackground", {
                repeat: true,
                colorList: ["#aaa", "#bbb", "#ccc"]
              });
            }
          }
        ]
      },
      {
        group: lang.aligntd,
        icon: "aligntd",
        subMenu: [
          {
            cmdName: "cellalignment",
            value: { align: "left", vAlign: "top" }
          },
          {
            cmdName: "cellalignment",
            value: { align: "center", vAlign: "top" }
          },
          {
            cmdName: "cellalignment",
            value: { align: "right", vAlign: "top" }
          },
          {
            cmdName: "cellalignment",
            value: { align: "left", vAlign: "middle" }
          },
          {
            cmdName: "cellalignment",
            value: { align: "center", vAlign: "middle" }
          },
          {
            cmdName: "cellalignment",
            value: { align: "right", vAlign: "middle" }
          },
          {
            cmdName: "cellalignment",
            value: { align: "left", vAlign: "bottom" }
          },
          {
            cmdName: "cellalignment",
            value: { align: "center", vAlign: "bottom" }
          },
          {
            cmdName: "cellalignment",
            value: { align: "right", vAlign: "bottom" }
          }
        ]
      },
      {
        group: lang.aligntable,
        icon: "aligntable",
        subMenu: [
          {
            cmdName: "tablealignment",
            className: "left",
            label: lang.tableleft,
            value: "left"
          },
          {
            cmdName: "tablealignment",
            className: "center",
            label: lang.tablecenter,
            value: "center"
          },
          {
            cmdName: "tablealignment",
            className: "right",
            label: lang.tableright,
            value: "right"
          }
        ]
      },
      "-",
      {
        label: lang.insertparagraphbefore,
        cmdName: "insertparagraph",
        value: true
      },
      {
        label: lang.insertparagraphafter,
        cmdName: "insertparagraph"
      },
      {
        label: lang["copy"],
        cmdName: "copy"
      },
      {
        label: lang["paste"],
        cmdName: "paste"
      }
    ];
  if (!items.length) {
    return;
  }
  var uiUtils = UE.ui.uiUtils;
  me.addListener("contextmenu", function(type, evt) {
    var offset = uiUtils.getViewportOffsetByEvent(evt);
    me.fireEvent("beforeselectionchange");
    if (menu) {
      menu.destroy();
    }
    for (var i = 0, ti, contextItems = []; (ti = items[i]); i++) {
      var last;
      (function(item) {
        if (item == "-") {
          if ((last = contextItems[contextItems.length - 1]) && last !== "-") {
            contextItems.push("-");
          }
        } else if (item.hasOwnProperty("group")) {
          for (var j = 0, cj, subMenu = []; (cj = item.subMenu[j]); j++) {
            (function(subItem) {
              if (subItem == "-") {
                if ((last = subMenu[subMenu.length - 1]) && last !== "-") {
                  subMenu.push("-");
                } else {
                  subMenu.splice(subMenu.length - 1);
                }
              } else {
                if (
                  (me.commands[subItem.cmdName] ||
                    UE.commands[subItem.cmdName] ||
                    subItem.query) &&
                  (subItem.query
                    ? subItem.query()
                    : me.queryCommandState(subItem.cmdName)) > -1
                ) {
                  subMenu.push({
                    label:
                      subItem.label ||
                        me.getLang(
                          "contextMenu." +
                            subItem.cmdName +
                            (subItem.value || "")
                        ) ||
                        "",
                    className:
                      "edui-for-" +
                        subItem.cmdName +
                        (subItem.className
                          ? " edui-for-" +
                              subItem.cmdName +
                              "-" +
                              subItem.className
                          : ""),
                    onclick: subItem.exec
                      ? function() {
                          subItem.exec.call(me);
                        }
                      : function() {
                          me.execCommand(subItem.cmdName, subItem.value);
                        }
                  });
                }
              }
            })(cj);
          }
          if (subMenu.length) {
            function getLabel() {
              switch (item.icon) {
                case "table":
                  return me.getLang("contextMenu.table");
                case "justifyjustify":
                  return me.getLang("contextMenu.paragraph");
                case "aligntd":
                  return me.getLang("contextMenu.aligntd");
                case "aligntable":
                  return me.getLang("contextMenu.aligntable");
                case "tablesort":
                  return lang.tablesort;
                case "borderBack":
                  return lang.borderbk;
                default:
                  return "";
              }
            }
            contextItems.push({
              //todo 修正成自动获取方式
              label: getLabel(),
              className: "edui-for-" + item.icon,
              subMenu: {
                items: subMenu,
                editor: me
              }
            });
          }
        } else {
          //有可能commmand没有加载右键不能出来,或者没有command也想能展示出来添加query方法
          if (
            (me.commands[item.cmdName] ||
              UE.commands[item.cmdName] ||
              item.query) &&
            (item.query
              ? item.query.call(me)
              : me.queryCommandState(item.cmdName)) > -1
          ) {
            contextItems.push({
              label: item.label || me.getLang("contextMenu." + item.cmdName),
              className:
                "edui-for-" +
                  (item.icon ? item.icon : item.cmdName + (item.value || "")),
              onclick: item.exec
                ? function() {
                    item.exec.call(me);
                  }
                : function() {
                    me.execCommand(item.cmdName, item.value);
                  }
            });
          }
        }
      })(ti);
    }
    if (contextItems[contextItems.length - 1] == "-") {
      contextItems.pop();
    }
    menu = new UE.ui.Menu({
      items: contextItems,
      className: "edui-contextmenu",
      editor: me
    });
    menu.render();
    menu.showAt(offset);
    me.fireEvent("aftershowcontextmenu", menu);
    domUtils.preventDefault(evt);
    if (browser.ie) {
      var ieRange;
      try {
        ieRange = me.selection.getNative().createRange();
      } catch (e) {
        return;
      }
      if (ieRange.item) {
        var range = new dom.Range(me.document);
        range.selectNode(ieRange.item(0)).select(true, true);
      }
    }
  });
  // 添加复制的flash按钮
  me.addListener("aftershowcontextmenu", function(type, menu) {
    if (me.zeroclipboard) {
      var items = menu.items;
      for (var key in items) {
        if (items[key].className == "edui-for-copy") {
          me.zeroclipboard.clip(items[key].getDom());
        }
      }
    }
  });
};
// plugins/shortcutmenu.js
///import core
///commands       弹出菜单
// commandsName  popupmenu
///commandsTitle  弹出菜单
/**
 * 弹出菜单
 * @function
 * @name baidu.editor.plugins.popupmenu
 * @author xuheng
 */
UE.plugins["shortcutmenu"] = function() {
  var me = this,
    menu,
    items = me.options.shortcutMenu || [];
  if (!items.length) {
    return;
  }
  me.addListener("contextmenu mouseup", function(type, e) {
    var me = this,
      customEvt = {
        type: type,
        target: e.target || e.srcElement,
        screenX: e.screenX,
        screenY: e.screenY,
        clientX: e.clientX,
        clientY: e.clientY
      };
    setTimeout(function() {
      var rng = me.selection.getRange();
      if (rng.collapsed === false || type == "contextmenu") {
        if (!menu) {
          menu = new baidu.editor.ui.ShortCutMenu({
            editor: me,
            items: items,
            theme: me.options.theme,
            className: "edui-shortcutmenu"
          });
          menu.render();
          me.fireEvent("afterrendershortcutmenu", menu);
        }
        menu.show(customEvt, !!UE.plugins["contextmenu"]);
      }
    });
    if (type == "contextmenu") {
      domUtils.preventDefault(e);
      if (browser.ie9below) {
        var ieRange;
        try {
          ieRange = me.selection.getNative().createRange();
        } catch (e) {
          return;
        }
        if (ieRange.item) {
          var range = new dom.Range(me.document);
          range.selectNode(ieRange.item(0)).select(true, true);
        }
      }
    }
  });
  me.addListener("keydown", function(type) {
    if (type == "keydown") {
      menu && !menu.isHidden && menu.hide();
    }
  });
};
// plugins/basestyle.js
/**
 * B、I、sub、super命令支持
 * @file
 * @since 1.2.6.1
 */
UE.plugins["basestyle"] = function() {
  /**
     * 字体加粗
     * @command bold
     * @param { String } cmd 命令字符串
     * @remind 对已加粗的文本内容执行该命令, 将取消加粗
     * @method execCommand
     * @example
     * ```javascript
     * //editor是编辑器实例
     * //对当前选中的文本内容执行加粗操作
     * //第一次执行, 文本内容加粗
     * editor.execCommand( 'bold' );
     *
     * //第二次执行, 文本内容取消加粗
     * editor.execCommand( 'bold' );
     * ```
     */
  /**
     * 字体倾斜
     * @command italic
     * @method execCommand
     * @param { String } cmd 命令字符串
     * @remind 对已倾斜的文本内容执行该命令, 将取消倾斜
     * @example
     * ```javascript
     * //editor是编辑器实例
     * //对当前选中的文本内容执行斜体操作
     * //第一次操作, 文本内容将变成斜体
     * editor.execCommand( 'italic' );
     *
     * //再次对同一文本内容执行, 则文本内容将恢复正常
     * editor.execCommand( 'italic' );
     * ```
     */
  /**
     * 下标文本,与“superscript”命令互斥
     * @command subscript
     * @method execCommand
     * @remind  把选中的文本内容切换成下标文本, 如果当前选中的文本已经是下标, 则该操作会把文本内容还原成正常文本
     * @param { String } cmd 命令字符串
     * @example
     * ```javascript
     * //editor是编辑器实例
     * //对当前选中的文本内容执行下标操作
     * //第一次操作, 文本内容将变成下标文本
     * editor.execCommand( 'subscript' );
     *
     * //再次对同一文本内容执行, 则文本内容将恢复正常
     * editor.execCommand( 'subscript' );
     * ```
     */
  /**
     * 上标文本,与“subscript”命令互斥
     * @command superscript
     * @method execCommand
     * @remind 把选中的文本内容切换成上标文本, 如果当前选中的文本已经是上标, 则该操作会把文本内容还原成正常文本
     * @param { String } cmd 命令字符串
     * @example
     * ```javascript
     * //editor是编辑器实例
     * //对当前选中的文本内容执行上标操作
     * //第一次操作, 文本内容将变成上标文本
     * editor.execCommand( 'superscript' );
     *
     * //再次对同一文本内容执行, 则文本内容将恢复正常
     * editor.execCommand( 'superscript' );
     * ```
     */
  var basestyles = {
    bold: ["strong", "b"],
    italic: ["em", "i"],
    subscript: ["sub"],
    superscript: ["sup"]
  },
    getObj = function(editor, tagNames) {
      return domUtils.filterNodeList(
        editor.selection.getStartElementPath(),
        tagNames
      );
    },
    me = this;
  //添加快捷键
  me.addshortcutkey({
    Bold: "ctrl+66", //^B
    Italic: "ctrl+73", //^I
    Underline: "ctrl+85" //^U
  });
  me.addInputRule(function(root) {
    utils.each(root.getNodesByTagName("b i"), function(node) {
      switch (node.tagName) {
        case "b":
          node.tagName = "strong";
          break;
        case "i":
          node.tagName = "em";
      }
    });
  });
  for (var style in basestyles) {
    (function(cmd, tagNames) {
      me.commands[cmd] = {
        execCommand: function(cmdName) {
          var range = me.selection.getRange(),
            obj = getObj(this, tagNames);
          if (range.collapsed) {
            if (obj) {
              var tmpText = me.document.createTextNode("");
              range.insertNode(tmpText).removeInlineStyle(tagNames);
              range.setStartBefore(tmpText);
              domUtils.remove(tmpText);
            } else {
              var tmpNode = range.document.createElement(tagNames[0]);
              if (cmdName == "superscript" || cmdName == "subscript") {
                tmpText = me.document.createTextNode("");
                range
                  .insertNode(tmpText)
                  .removeInlineStyle(["sub", "sup"])
                  .setStartBefore(tmpText)
                  .collapse(true);
              }
              range.insertNode(tmpNode).setStart(tmpNode, 0);
            }
            range.collapse(true);
          } else {
            if (cmdName == "superscript" || cmdName == "subscript") {
              if (!obj || obj.tagName.toLowerCase() != cmdName) {
                range.removeInlineStyle(["sub", "sup"]);
              }
            }
            obj
              ? range.removeInlineStyle(tagNames)
              : range.applyInlineStyle(tagNames[0]);
          }
          range.select();
        },
        queryCommandState: function() {
          return getObj(this, tagNames) ? 1 : 0;
        }
      };
    })(style, basestyles[style]);
  }
};
// plugins/elementpath.js
/**
 * 选取路径命令
 * @file
 */
UE.plugins["elementpath"] = function() {
  var currentLevel,
    tagNames,
    me = this;
  me.setOpt("elementPathEnabled", true);
  if (!me.options.elementPathEnabled) {
    return;
  }
  me.commands["elementpath"] = {
    execCommand: function(cmdName, level) {
      var start = tagNames[level],
        range = me.selection.getRange();
      currentLevel = level * 1;
      range.selectNode(start).select();
    },
    queryCommandValue: function() {
      //产生一个副本,不能修改原来的startElementPath;
      var parents = [].concat(this.selection.getStartElementPath()).reverse(),
        names = [];
      tagNames = parents;
      for (var i = 0, ci; (ci = parents[i]); i++) {
        if (ci.nodeType == 3) {
          continue;
        }
        var name = ci.tagName.toLowerCase();
        if (name == "img" && ci.getAttribute("anchorname")) {
          name = "anchor";
        }
        names[i] = name;
        if (currentLevel == i) {
          currentLevel = -1;
          break;
        }
      }
      return names;
    }
  };
};
// plugins/formatmatch.js
/**
 * 格式刷,只格式inline的
 * @file
 * @since 1.2.6.1
 */
/**
 * 格式刷
 * @command formatmatch
 * @method execCommand
 * @remind 该操作不能复制段落格式
 * @param { String } cmd 命令字符串
 * @example
 * ```javascript
 * //editor是编辑器实例
 * //获取格式刷
 * editor.execCommand( 'formatmatch' );
 * ```
 */
UE.plugins["formatmatch"] = function() {
  var me = this,
    list = [],
    img,
    flag = 0;
  me.addListener("reset", function() {
    list = [];
    flag = 0;
  });
  function addList(type, evt) {
    if (browser.webkit) {
      var target = evt.target.tagName == "IMG" ? evt.target : null;
    }
    function addFormat(range) {
      if (text) {
        range.selectNode(text);
      }
      return range.applyInlineStyle(list[list.length - 1].tagName, null, list);
    }
    me.undoManger && me.undoManger.save();
    var range = me.selection.getRange(),
      imgT = target || range.getClosedNode();
    if (img && imgT && imgT.tagName == "IMG") {
      //trace:964
      imgT.style.cssText +=
        ";float:" +
        (img.style.cssFloat || img.style.styleFloat || "none") +
        ";display:" +
        (img.style.display || "inline");
      img = null;
    } else {
      if (!img) {
        var collapsed = range.collapsed;
        if (collapsed) {
          var text = me.document.createTextNode("match");
          range.insertNode(text).select();
        }
        me.__hasEnterExecCommand = true;
        //不能把block上的属性干掉
        //trace:1553
        var removeFormatAttributes = me.options.removeFormatAttributes;
        me.options.removeFormatAttributes = "";
        me.execCommand("removeformat");
        me.options.removeFormatAttributes = removeFormatAttributes;
        me.__hasEnterExecCommand = false;
        //trace:969
        range = me.selection.getRange();
        if (list.length) {
          addFormat(range);
        }
        if (text) {
          range.setStartBefore(text).collapse(true);
        }
        range.select();
        text && domUtils.remove(text);
      }
    }
    me.undoManger && me.undoManger.save();
    me.removeListener("mouseup", addList);
    flag = 0;
  }
  me.commands["formatmatch"] = {
    execCommand: function(cmdName) {
      if (flag) {
        flag = 0;
        list = [];
        me.removeListener("mouseup", addList);
        return;
      }
      var range = me.selection.getRange();
      img = range.getClosedNode();
      if (!img || img.tagName != "IMG") {
        range.collapse(true).shrinkBoundary();
        var start = range.startContainer;
        list = domUtils.findParents(start, true, function(node) {
          return !domUtils.isBlockElm(node) && node.nodeType == 1;
        });
        //a不能加入格式刷, 并且克隆节点
        for (var i = 0, ci; (ci = list[i]); i++) {
          if (ci.tagName == "A") {
            list.splice(i, 1);
            break;
          }
        }
      }
      me.addListener("mouseup", addList);
      flag = 1;
    },
    queryCommandState: function() {
      return flag;
    },
    notNeedUndo: 1
  };
};
// plugins/searchreplace.js
///import core
///commands 查找替换
///commandsName  SearchReplace
///commandsTitle  查询替换
///commandsDialog  dialogs\searchreplace
/**
 * @description 查找替换
 * @author zhanyi
 */
UE.plugin.register("searchreplace", function() {
  var me = this;
  var _blockElm = { table: 1, tbody: 1, tr: 1, ol: 1, ul: 1 };
  var lastRng = null;
  function getText(node) {
    var text = node.nodeType == 3
      ? node.nodeValue
      : node[browser.ie ? "innerText" : "textContent"];
    return text.replace(domUtils.fillChar, "");
  }
  function findTextInString(textContent, opt, currentIndex) {
    var str = opt.searchStr;
    var reg = new RegExp(str, "g" + (opt.casesensitive ? "" : "i")),
      match;
    if (opt.dir == -1) {
      textContent = textContent.substr(0, currentIndex);
      textContent = textContent.split("").reverse().join("");
      str = str.split("").reverse().join("");
      match = reg.exec(textContent);
      if (match) {
        return currentIndex - match.index - str.length;
      }
    } else {
      textContent = textContent.substr(currentIndex);
      match = reg.exec(textContent);
      if (match) {
        return match.index + currentIndex;
      }
    }
    return -1;
  }
  function findTextBlockElm(node, currentIndex, opt) {
    var textContent,
      index,
      methodName = opt.all || opt.dir == 1 ? "getNextDomNode" : "getPreDomNode";
    if (domUtils.isBody(node)) {
      node = node.firstChild;
    }
    var first = 1;
    while (node) {
      textContent = getText(node);
      index = findTextInString(textContent, opt, currentIndex);
      first = 0;
      if (index != -1) {
        return {
          node: node,
          index: index
        };
      }
      node = domUtils[methodName](node);
      while (node && _blockElm[node.nodeName.toLowerCase()]) {
        node = domUtils[methodName](node, true);
      }
      if (node) {
        currentIndex = opt.dir == -1 ? getText(node).length : 0;
      }
    }
  }
  function findNTextInBlockElm(node, index, str) {
    var currentIndex = 0,
      currentNode = node.firstChild,
      currentNodeLength = 0,
      result;
    while (currentNode) {
      if (currentNode.nodeType == 3) {
        currentNodeLength = getText(currentNode).replace(
          /(^[\t\r\n]+)|([\t\r\n]+$)/,
          ""
        ).length;
        currentIndex += currentNodeLength;
        if (currentIndex >= index) {
          return {
            node: currentNode,
            index: currentNodeLength - (currentIndex - index)
          };
        }
      } else if (!dtd.$empty[currentNode.tagName]) {
        currentNodeLength = getText(currentNode).replace(
          /(^[\t\r\n]+)|([\t\r\n]+$)/,
          ""
        ).length;
        currentIndex += currentNodeLength;
        if (currentIndex >= index) {
          result = findNTextInBlockElm(
            currentNode,
            currentNodeLength - (currentIndex - index),
            str
          );
          if (result) {
            return result;
          }
        }
      }
      currentNode = domUtils.getNextDomNode(currentNode);
    }
  }
  function searchReplace(me, opt) {
    var rng = lastRng || me.selection.getRange(),
      startBlockNode,
      searchStr = opt.searchStr,
      span = me.document.createElement("span");
    span.innerHTML = "$$ueditor_searchreplace_key$$";
    rng.shrinkBoundary(true);
    //判断是不是第一次选中
    if (!rng.collapsed) {
      rng.select();
      var rngText = me.selection.getText();
      if (
        new RegExp(
          "^" + opt.searchStr + "$",
          opt.casesensitive ? "" : "i"
        ).test(rngText)
      ) {
        if (opt.replaceStr != undefined) {
          replaceText(rng, opt.replaceStr);
          rng.select();
          return true;
        } else {
          rng.collapse(opt.dir == -1);
        }
      }
    }
    rng.insertNode(span);
    rng.enlargeToBlockElm(true);
    startBlockNode = rng.startContainer;
    var currentIndex = getText(startBlockNode).indexOf(
      "$$ueditor_searchreplace_key$$"
    );
    rng.setStartBefore(span);
    domUtils.remove(span);
    var result = findTextBlockElm(startBlockNode, currentIndex, opt);
    if (result) {
      var rngStart = findNTextInBlockElm(result.node, result.index, searchStr);
      var rngEnd = findNTextInBlockElm(
        result.node,
        result.index + searchStr.length,
        searchStr
      );
      rng
        .setStart(rngStart.node, rngStart.index)
        .setEnd(rngEnd.node, rngEnd.index);
      if (opt.replaceStr !== undefined) {
        replaceText(rng, opt.replaceStr);
      }
      rng.select();
      return true;
    } else {
      rng.setCursor();
    }
  }
  function replaceText(rng, str) {
    str = me.document.createTextNode(str);
    rng.deleteContents().insertNode(str);
  }
  return {
    commands: {
      searchreplace: {
        execCommand: function(cmdName, opt) {
          utils.extend(
            opt,
            {
              all: false,
              casesensitive: false,
              dir: 1
            },
            true
          );
          var num = 0;
          if (opt.all) {
            lastRng = null;
            var rng = me.selection.getRange(),
              first = me.body.firstChild;
            if (first && first.nodeType == 1) {
              rng.setStart(first, 0);
              rng.shrinkBoundary(true);
            } else if (first.nodeType == 3) {
              rng.setStartBefore(first);
            }
            rng.collapse(true).select(true);
            if (opt.replaceStr !== undefined) {
              me.fireEvent("saveScene");
            }
            while (searchReplace(this, opt)) {
              num++;
              lastRng = me.selection.getRange();
              lastRng.collapse(opt.dir == -1);
            }
            if (num) {
              me.fireEvent("saveScene");
            }
          } else {
            if (opt.replaceStr !== undefined) {
              me.fireEvent("saveScene");
            }
            if (searchReplace(this, opt)) {
              num++;
              lastRng = me.selection.getRange();
              lastRng.collapse(opt.dir == -1);
            }
            if (num) {
              me.fireEvent("saveScene");
            }
          }
          return num;
        },
        notNeedUndo: 1
      }
    },
    bindEvents: {
      clearlastSearchResult: function() {
        lastRng = null;
      }
    }
  };
});
// plugins/customstyle.js
/**
 * 自定义样式
 * @file
 * @since 1.2.6.1
 */
/**
 * 根据config配置文件里“customstyle”选项的值对匹配的标签执行样式替换。
 * @command customstyle
 * @method execCommand
 * @param { String } cmd 命令字符串
 * @example
 * ```javascript
 * editor.execCommand( 'customstyle' );
 * ```
 */
UE.plugins["customstyle"] = function() {
  var me = this;
  me.setOpt({
    customstyle: [
      {
        tag: "h1",
        name: "tc",
        style:
          "font-size:32px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;margin:0 0 20px 0;"
      },
      {
        tag: "h1",
        name: "tl",
        style:
          "font-size:32px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:left;margin:0 0 10px 0;"
      },
      {
        tag: "span",
        name: "im",
        style:
          "font-size:16px;font-style:italic;font-weight:bold;line-height:18px;"
      },
      {
        tag: "span",
        name: "hi",
        style:
          "font-size:16px;font-style:italic;font-weight:bold;color:rgb(51, 153, 204);line-height:18px;"
      }
    ]
  });
  me.commands["customstyle"] = {
    execCommand: function(cmdName, obj) {
      var me = this,
        tagName = obj.tag,
        node = domUtils.findParent(
          me.selection.getStart(),
          function(node) {
            return node.getAttribute("label");
          },
          true
        ),
        range,
        bk,
        tmpObj = {};
      for (var p in obj) {
        if (obj[p] !== undefined) tmpObj[p] = obj[p];
      }
      delete tmpObj.tag;
      if (node && node.getAttribute("label") == obj.label) {
        range = this.selection.getRange();
        bk = range.createBookmark();
        if (range.collapsed) {
          //trace:1732 删掉自定义标签,要有p来回填站位
          if (dtd.$block[node.tagName]) {
            var fillNode = me.document.createElement("p");
            domUtils.moveChild(node, fillNode);
            node.parentNode.insertBefore(fillNode, node);
            domUtils.remove(node);
          } else {
            domUtils.remove(node, true);
          }
        } else {
          var common = domUtils.getCommonAncestor(bk.start, bk.end),
            nodes = domUtils.getElementsByTagName(common, tagName);
          if (new RegExp(tagName, "i").test(common.tagName)) {
            nodes.push(common);
          }
          for (var i = 0, ni; (ni = nodes[i++]); ) {
            if (ni.getAttribute("label") == obj.label) {
              var ps = domUtils.getPosition(ni, bk.start),
                pe = domUtils.getPosition(ni, bk.end);
              if (
                (ps & domUtils.POSITION_FOLLOWING ||
                  ps & domUtils.POSITION_CONTAINS) &&
                (pe & domUtils.POSITION_PRECEDING ||
                  pe & domUtils.POSITION_CONTAINS)
              )
                if (dtd.$block[tagName]) {
                  var fillNode = me.document.createElement("p");
                  domUtils.moveChild(ni, fillNode);
                  ni.parentNode.insertBefore(fillNode, ni);
                }
              domUtils.remove(ni, true);
            }
          }
          node = domUtils.findParent(
            common,
            function(node) {
              return node.getAttribute("label") == obj.label;
            },
            true
          );
          if (node) {
            domUtils.remove(node, true);
          }
        }
        range.moveToBookmark(bk).select();
      } else {
        if (dtd.$block[tagName]) {
          this.execCommand("paragraph", tagName, tmpObj, "customstyle");
          range = me.selection.getRange();
          if (!range.collapsed) {
            range.collapse();
            node = domUtils.findParent(
              me.selection.getStart(),
              function(node) {
                return node.getAttribute("label") == obj.label;
              },
              true
            );
            var pNode = me.document.createElement("p");
            domUtils.insertAfter(node, pNode);
            domUtils.fillNode(me.document, pNode);
            range.setStart(pNode, 0).setCursor();
          }
        } else {
          range = me.selection.getRange();
          if (range.collapsed) {
            node = me.document.createElement(tagName);
            domUtils.setAttributes(node, tmpObj);
            range.insertNode(node).setStart(node, 0).setCursor();
            return;
          }
          bk = range.createBookmark();
          range.applyInlineStyle(tagName, tmpObj).moveToBookmark(bk).select();
        }
      }
    },
    queryCommandValue: function() {
      var parent = domUtils.filterNodeList(
        this.selection.getStartElementPath(),
        function(node) {
          return node.getAttribute("label");
        }
      );
      return parent ? parent.getAttribute("label") : "";
    }
  };
  //当去掉customstyle是,如果是块元素,用p代替
  me.addListener("keyup", function(type, evt) {
    var keyCode = evt.keyCode || evt.which;
    if (keyCode == 32 || keyCode == 13) {
      var range = me.selection.getRange();
      if (range.collapsed) {
        var node = domUtils.findParent(
          me.selection.getStart(),
          function(node) {
            return node.getAttribute("label");
          },
          true
        );
        if (node && dtd.$block[node.tagName] && domUtils.isEmptyNode(node)) {
          var p = me.document.createElement("p");
          domUtils.insertAfter(node, p);
          domUtils.fillNode(me.document, p);
          domUtils.remove(node);
          range.setStart(p, 0).setCursor();
        }
      }
    }
  });
};
// plugins/catchremoteimage.js
///import core
///commands 远程图片抓取
///commandsName  catchRemoteImage,catchremoteimageenable
///commandsTitle  远程图片抓取
/**
 * 远程图片抓取,当开启本插件时所有不符合本地域名的图片都将被抓取成为本地服务器上的图片
 */
UE.plugins["catchremoteimage"] = function() {
  var me = this,
    ajax = UE.ajax;
  /* 设置默认值 */
  if (me.options.catchRemoteImageEnable === false) return;
  me.setOpt({
    catchRemoteImageEnable: false
  });
  me.addListener("afterpaste", function() {
    me.fireEvent("catchRemoteImage");
  });
  me.addListener("catchRemoteImage", function() {
    var catcherLocalDomain = me.getOpt("catcherLocalDomain"),
      catcherActionUrl = me.getActionUrl(me.getOpt("catcherActionName")),
      catcherUrlPrefix = me.getOpt("catcherUrlPrefix"),
      catcherFieldName = me.getOpt("catcherFieldName");
    var remoteImages = [],
      loadingIMG =  me.options.themePath + me.options.theme + '/images/spacer.gif',
      imgs = me.document.querySelectorAll('[style*="url"],img'),
      test = function(src, urls) {
        if (src.indexOf(location.host) != -1 || /(^\.)|(^\/)/.test(src)) {
          return true;
        }
        if (urls) {
          for (var j = 0, url; (url = urls[j++]); ) {
            if (src.indexOf(url) !== -1) {
              return true;
            }
          }
        }
        return false;
      };
    for (var i = 0, ci; (ci = imgs[i++]); ) {
      if (ci.getAttribute("word_img")) {
        continue;
      }
      if(ci.nodeName == "IMG"){
        var src = ci.getAttribute("_src") || ci.src || "";
        if (/^(https?|ftp):/i.test(src) && !test(src, catcherLocalDomain)) {
          remoteImages.push(src);
          // 添加上传时的uploading动画
          domUtils.setAttributes(ci, {
            class: "loadingclass",
            _src: src,
            src: loadingIMG
          })
        }
      } else {
        // 获取背景图片url
        var backgroundImageurl = ci.style.cssText.replace(/.*\s?url\([\'\"]?/, '').replace(/[\'\"]?\).*/, '');
        if (/^(https?|ftp):/i.test(backgroundImageurl) && !test(backgroundImageurl, catcherLocalDomain)) {
          remoteImages.push(backgroundImageurl);
          ci.style.cssText = ci.style.cssText.replace(backgroundImageurl, loadingIMG);
          domUtils.setAttributes(ci, {
            "data-background": backgroundImageurl
          })
        }
      }
    }
    if (remoteImages.length) {
      catchremoteimage(remoteImages, {
        //成功抓取
        success: function(r) {
          try {
            var info = r.state !== undefined
              ? r
              : eval("(" + r.responseText + ")");
          } catch (e) {
            return;
          }
          /* 获取源路径和新路径 */
          var i,
            j,
            ci,
            cj,
            oldSrc,
            newSrc,
            list = info.list;
          /* 抓取失败统计 */
          var catchFailList = [];
          /* 抓取成功统计 */
          var catchSuccessList = [];
          /* 抓取失败时显示的图片 */
          var failIMG = me.options.themePath + me.options.theme + '/images/img-cracked.png';
          for (i = 0; ci = imgs[i++];) {
            oldSrc = ci.getAttribute("_src") || ci.src || "";
            oldBgIMG = ci.getAttribute("data-background") || "";
            for (j = 0; cj = list[j++];) {
              if (oldSrc == cj.source && cj.state == "SUCCESS") {
                newSrc = catcherUrlPrefix + cj.url;
                // 上传成功是删除uploading动画
                domUtils.removeClasses( ci, "loadingclass" );
                domUtils.setAttributes(ci, {
                    "src": newSrc,
                    "_src": newSrc,
                    "data-catchResult":"img_catchSuccess"   // 添加catch成功标记
                });
                catchSuccessList.push(ci);
                break;
              } else if (oldSrc == cj.source && cj.state == "FAIL") {
                // 替换成统一的失败图片
                domUtils.removeClasses( ci, "loadingclass" );
                domUtils.setAttributes(ci, {
                    "src": failIMG,
                    "_src": failIMG,
                    "data-catchResult":"img_catchFail" // 添加catch失败标记
                });
                catchFailList.push(ci);
                break;
              } else if (oldBgIMG == cj.source && cj.state == "SUCCESS") {
                newBgIMG = catcherUrlPrefix + cj.url;
                ci.style.cssText = ci.style.cssText.replace(loadingIMG, newBgIMG);
                domUtils.removeAttributes(ci,"data-background");
                domUtils.setAttributes(ci, {
                    "data-catchResult":"img_catchSuccess"   // 添加catch成功标记
                });
                catchSuccessList.push(ci);
                break;
              } else if (oldBgIMG == cj.source && cj.state == "FAIL"){
                ci.style.cssText = ci.style.cssText.replace(loadingIMG, failIMG);
                domUtils.removeAttributes(ci,"data-background");
                domUtils.setAttributes(ci, {
                    "data-catchResult":"img_catchFail"   // 添加catch失败标记
                });
                catchFailList.push(ci);
                break;
              }
            }
          }
          // 监听事件添加成功抓取和抓取失败的dom列表参数
          me.fireEvent('catchremotesuccess',catchSuccessList,catchFailList);
        },
        //回调失败,本次请求超时
        error: function() {
          me.fireEvent("catchremoteerror");
        }
      });
    }
    function catchremoteimage(imgs, callbacks) {
      var params =
        utils.serializeParam(me.queryCommandValue("serverparam")) || "",
        url = utils.formatUrl(
          catcherActionUrl +
            (catcherActionUrl.indexOf("?") == -1 ? "?" : "&") +
            params
        ),
        isJsonp = utils.isCrossDomainUrl(url),
        opt = {
          method: "POST",
          dataType: isJsonp ? "jsonp" : "",
          timeout: 60000, //单位:毫秒,回调请求超时设置。目标用户如果网速不是很快的话此处建议设置一个较大的数值
          onsuccess: callbacks["success"],
          onerror: callbacks["error"]
        };
      opt[catcherFieldName] = imgs;
      ajax.request(url, opt);
    }
  });
};
// plugins/snapscreen.js
/**
 * 截屏插件,为UEditor提供插入支持
 * @file
 * @since 1.4.2
 */
UE.plugin.register("snapscreen", function() {
  var me = this;
  var snapplugin;
  function getLocation(url) {
    var search,
      a = document.createElement("a"),
      params = utils.serializeParam(me.queryCommandValue("serverparam")) || "";
    a.href = url;
    if (browser.ie) {
      a.href = a.href;
    }
    search = a.search;
    if (params) {
      search = search + (search.indexOf("?") == -1 ? "?" : "&") + params;
      search = search.replace(/[&]+/gi, "&");
    }
    return {
      port: a.port,
      hostname: a.hostname,
      path: a.pathname + search || +a.hash
    };
  }
  return {
    commands: {
      /**
             * 字体背景颜色
             * @command snapscreen
             * @method execCommand
             * @param { String } cmd 命令字符串
             * @example
             * ```javascript
             * editor.execCommand('snapscreen');
             * ```
             */
      snapscreen: {
        execCommand: function(cmd) {
          var url, local, res;
          var lang = me.getLang("snapScreen_plugin");
          if (!snapplugin) {
            var container = me.container;
            var doc = me.container.ownerDocument || me.container.document;
            snapplugin = doc.createElement("object");
            try {
              snapplugin.type = "application/x-pluginbaidusnap";
            } catch (e) {
              return;
            }
            snapplugin.style.cssText =
              "position:absolute;left:-9999px;width:0;height:0;";
            snapplugin.setAttribute("width", "0");
            snapplugin.setAttribute("height", "0");
            container.appendChild(snapplugin);
          }
          function onSuccess(rs) {
            try {
              rs = eval("(" + rs + ")");
              if (rs.state == "SUCCESS") {
                var opt = me.options;
                me.execCommand("insertimage", {
                  src: opt.snapscreenUrlPrefix + rs.url,
                  _src: opt.snapscreenUrlPrefix + rs.url,
                  alt: rs.title || "",
                  floatStyle: opt.snapscreenImgAlign
                });
              } else {
                alert(rs.state);
              }
            } catch (e) {
              alert(lang.callBackErrorMsg);
            }
          }
          url = me.getActionUrl(me.getOpt("snapscreenActionName"));
          local = getLocation(url);
          setTimeout(function() {
            try {
              res = snapplugin.saveSnapshot(
                local.hostname,
                local.path,
                local.port
              );
            } catch (e) {
              me.ui._dialogs["snapscreenDialog"].open();
              return;
            }
            onSuccess(res);
          }, 50);
        },
        queryCommandState: function() {
          return navigator.userAgent.indexOf("Windows", 0) != -1 ? 0 : -1;
        }
      }
    }
  };
});
// plugins/insertparagraph.js
/**
 * 插入段落
 * @file
 * @since 1.2.6.1
 */
/**
 * 插入段落
 * @command insertparagraph
 * @method execCommand
 * @param { String } cmd 命令字符串
 * @example
 * ```javascript
 * //editor是编辑器实例
 * editor.execCommand( 'insertparagraph' );
 * ```
 */
UE.commands["insertparagraph"] = {
  execCommand: function(cmdName, front) {
    var me = this,
      range = me.selection.getRange(),
      start = range.startContainer,
      tmpNode;
    while (start) {
      if (domUtils.isBody(start)) {
        break;
      }
      tmpNode = start;
      start = start.parentNode;
    }
    if (tmpNode) {
      var p = me.document.createElement("p");
      if (front) {
        tmpNode.parentNode.insertBefore(p, tmpNode);
      } else {
        tmpNode.parentNode.insertBefore(p, tmpNode.nextSibling);
      }
      domUtils.fillNode(me.document, p);
      range.setStart(p, 0).setCursor(false, true);
    }
  }
};
// plugins/webapp.js
/**
 * 百度应用
 * @file
 * @since 1.2.6.1
 */
/**
 * 插入百度应用
 * @command webapp
 * @method execCommand
 * @remind 需要百度APPKey
 * @remind 百度应用主页: http://app.baidu.com/ 
 * @param { Object } appOptions 应用所需的参数项, 支持的key有: title=>应用标题, width=>应用容器宽度,
 * height=>应用容器高度,logo=>应用logo,url=>应用地址
 * @example
 * ```javascript
 * //editor是编辑器实例
 * //在编辑器里插入一个“植物大战僵尸”的APP
 * editor.execCommand( 'webapp' , {
 *     title: '植物大战僵尸',
 *     width: 560,
 *     height: 465,
 *     logo: '应用展示的图片',
 *     url: '百度应用的地址'
 * } );
 * ```
 */
//UE.plugins['webapp'] = function () {
//    var me = this;
//    function createInsertStr( obj, toIframe, addParagraph ) {
//        return !toIframe ?
//                (addParagraph ? '' : '') + '
' : '')
//                :
//                '';
//    }
//
//    function switchImgAndIframe( img2frame ) {
//        var tmpdiv,
//                nodes = domUtils.getElementsByTagName( me.document, !img2frame ? "iframe" : "img" );
//        for ( var i = 0, node; node = nodes[i++]; ) {
//            if ( node.className != "edui-faked-webapp" ){
//                continue;
//            }
//            tmpdiv = me.document.createElement( "div" );
//            tmpdiv.innerHTML = createInsertStr( img2frame ? {url:node.getAttribute( "_url" ), width:node.width, height:node.height,title:node.title,logo:node.style.backgroundImage.replace("url(","").replace(")","")} : {url:node.getAttribute( "src", 2 ),title:node.title, width:node.width, height:node.height,logo:node.getAttribute("logo_url")}, img2frame ? true : false,false );
//            node.parentNode.replaceChild( tmpdiv.firstChild, node );
//        }
//    }
//
//    me.addListener( "beforegetcontent", function () {
//        switchImgAndIframe( true );
//    } );
//    me.addListener( 'aftersetcontent', function () {
//        switchImgAndIframe( false );
//    } );
//    me.addListener( 'aftergetcontent', function ( cmdName ) {
//        if ( cmdName == 'aftergetcontent' && me.queryCommandState( 'source' ) ){
//            return;
//        }
//        switchImgAndIframe( false );
//    } );
//
//    me.commands['webapp'] = {
//        execCommand:function ( cmd, obj ) {
//            me.execCommand( "inserthtml", createInsertStr( obj, false,true ) );
//        }
//    };
//};
UE.plugin.register("webapp", function() {
  var me = this;
  function createInsertStr(obj, toEmbed) {
    return !toEmbed
      ? 'http://app.baidu.com/ 
             * @param { Object } appOptions 应用所需的参数项, 支持的key有: title=>应用标题, width=>应用容器宽度,
             * height=>应用容器高度,logo=>应用logo,url=>应用地址
             * @example
             * ```javascript
             * //editor是编辑器实例
             * //在编辑器里插入一个“植物大战僵尸”的APP
             * editor.execCommand( 'webapp' , {
             *     title: '植物大战僵尸',
             *     width: 560,
             *     height: 465,
             *     logo: '应用展示的图片',
             *     url: '百度应用的地址'
             * } );
             * ```
             */
      webapp: {
        execCommand: function(cmd, obj) {
          var me = this,
            str = createInsertStr(
              utils.extend(obj, {
                align: "none"
              }),
              false
            );
          me.execCommand("inserthtml", str);
        },
        queryCommandState: function() {
          var me = this,
            img = me.selection.getRange().getClosedNode(),
            flag = img && img.className == "edui-faked-webapp";
          return flag ? 1 : 0;
        }
      }
    }
  };
});
// plugins/template.js
///import core
///import plugins\inserthtml.js
///import plugins\cleardoc.js
///commands 模板
///commandsName  template
///commandsTitle  模板
///commandsDialog  dialogs\template
UE.plugins["template"] = function() {
  UE.commands["template"] = {
    execCommand: function(cmd, obj) {
      obj.html && this.execCommand("inserthtml", obj.html);
    }
  };
  this.addListener("click", function(type, evt) {
    var el = evt.target || evt.srcElement,
      range = this.selection.getRange();
    var tnode = domUtils.findParent(
      el,
      function(node) {
        if (node.className && domUtils.hasClass(node, "ue_t")) {
          return node;
        }
      },
      true
    );
    tnode && range.selectNode(tnode).shrinkBoundary().select();
  });
  this.addListener("keydown", function(type, evt) {
    var range = this.selection.getRange();
    if (!range.collapsed) {
      if (!evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
        var tnode = domUtils.findParent(
          range.startContainer,
          function(node) {
            if (node.className && domUtils.hasClass(node, "ue_t")) {
              return node;
            }
          },
          true
        );
        if (tnode) {
          domUtils.removeClasses(tnode, ["ue_t"]);
        }
      }
    }
  });
};
// plugins/music.js
/**
 * 插入音乐命令
 * @file
 */
UE.plugin.register("music", function() {
  var me = this;
  function creatInsertStr(url, width, height, align, cssfloat, toEmbed) {
    return !toEmbed
      ? "';
  }
  return {
    outputRule: function(root) {
      utils.each(root.getNodesByTagName("img"), function(node) {
        var html;
        if (node.getAttr("class") == "edui-faked-music") {
          var cssfloat = node.getStyle("float");
          var align = node.getAttr("align");
          html = creatInsertStr(
            node.getAttr("_url"),
            node.getAttr("width"),
            node.getAttr("height"),
            align,
            cssfloat,
            true
          );
          var embed = UE.uNode.createElement(html);
          node.parentNode.replaceChild(embed, node);
        }
      });
    },
    inputRule: function(root) {
      utils.each(root.getNodesByTagName("embed"), function(node) {
        if (node.getAttr("class") == "edui-faked-music") {
          var cssfloat = node.getStyle("float");
          var align = node.getAttr("align");
          html = creatInsertStr(
            node.getAttr("src"),
            node.getAttr("width"),
            node.getAttr("height"),
            align,
            cssfloat,
            false
          );
          var img = UE.uNode.createElement(html);
          node.parentNode.replaceChild(img, node);
        }
      });
    },
    commands: {
      /**
             * 插入音乐
             * @command music
             * @method execCommand
             * @param { Object } musicOptions 插入音乐的参数项, 支持的key有: url=>音乐地址;
             * width=>音乐容器宽度;height=>音乐容器高度;align=>音乐文件的对齐方式, 可选值有: left, center, right, none
             * @example
             * ```javascript
             * //editor是编辑器实例
             * //在编辑器里插入一个“植物大战僵尸”的APP
             * editor.execCommand( 'music' , {
             *     width: 400,
             *     height: 95,
             *     align: "center",
             *     url: "音乐地址"
             * } );
             * ```
             */
      music: {
        execCommand: function(cmd, musicObj) {
          var me = this,
            str = creatInsertStr(
              musicObj.url,
              musicObj.width || 400,
              musicObj.height || 95,
              "none",
              false
            );
          me.execCommand("inserthtml", str);
        },
        queryCommandState: function() {
          var me = this,
            img = me.selection.getRange().getClosedNode(),
            flag = img && img.className == "edui-faked-music";
          return flag ? 1 : 0;
        }
      }
    }
  };
});
// plugins/autoupload.js
/**
 * @description
 * 1.拖放文件到编辑区域,自动上传并插入到选区
 * 2.插入粘贴板的图片,自动上传并插入到选区
 * @author Jinqn
 * @date 2013-10-14
 */
UE.plugin.register("autoupload", function() {
  function sendAndInsertFile(file, editor) {
    var me = editor;
    //模拟数据
    var fieldName,
      urlPrefix,
      maxSize,
      allowFiles,
      actionUrl,
      loadingHtml,
      errorHandler,
      successHandler,
      filetype = /image\/\w+/i.test(file.type) ? "image" : "file",
      loadingId = "loading_" + (+new Date()).toString(36);
    fieldName = me.getOpt(filetype + "FieldName");
    urlPrefix = me.getOpt(filetype + "UrlPrefix");
    maxSize = me.getOpt(filetype + "MaxSize");
    allowFiles = me.getOpt(filetype + "AllowFiles");
    actionUrl = me.getActionUrl(me.getOpt(filetype + "ActionName"));
    errorHandler = function(title) {
      var loader = me.document.getElementById(loadingId);
      loader && domUtils.remove(loader);
      me.fireEvent("showmessage", {
        id: loadingId,
        content: title,
        type: "error",
        timeout: 4000
      });
    };
    if (filetype == "image") {
      loadingHtml =
        '" +
        '
";
      successHandler = function(data) {
        var link = urlPrefix + data.url,
          loader = me.document.getElementById(loadingId);
        var rng = me.selection.getRange(),
          bk = rng.createBookmark();
        rng.selectNode(loader).select();
        me.execCommand("insertfile", { url: link });
        rng.moveToBookmark(bk).select();
      };
    }
    /* 插入loading的占位符 */
    me.execCommand("inserthtml", loadingHtml);
    /* 判断后端配置是否没有加载成功 */
    if (!me.getOpt(filetype + "ActionName")) {
      errorHandler(me.getLang("autoupload.errorLoadConfig"));
      return;
    }
    /* 判断文件大小是否超出限制 */
    if (file.size > maxSize) {
      errorHandler(me.getLang("autoupload.exceedSizeError"));
      return;
    }
    /* 判断文件格式是否超出允许 */
    var fileext = file.name ? file.name.substr(file.name.lastIndexOf(".")) : "";
    if (
      (fileext && filetype != "image") ||
      (allowFiles &&
        (allowFiles.join("") + ".").indexOf(fileext.toLowerCase() + ".") == -1)
    ) {
      errorHandler(me.getLang("autoupload.exceedTypeError"));
      return;
    }
    /* 创建Ajax并提交 */
    var xhr = new XMLHttpRequest(),
      fd = new FormData(),
      params = utils.serializeParam(me.queryCommandValue("serverparam")) || "",
      url = utils.formatUrl(
        actionUrl + (actionUrl.indexOf("?") == -1 ? "?" : "&") + params
      );
    fd.append(
      fieldName,
      file,
      file.name || "blob." + file.type.substr("image/".length)
    );
    fd.append("type", "ajax");
    xhr.open("post", url, true);
    xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
    xhr.addEventListener("load", function(e) {
      try {
        var json = new Function("return " + utils.trim(e.target.response))();
        if (json.state == "SUCCESS" && json.url) {
          successHandler(json);
        } else {
          errorHandler(json.state);
        }
      } catch (er) {
        errorHandler(me.getLang("autoupload.loadError"));
      }
    });
    xhr.send(fd);
  }
  function getPasteImage(e) {
    return e.clipboardData &&
      e.clipboardData.items &&
      e.clipboardData.items.length == 1 &&
      /^image\//.test(e.clipboardData.items[0].type)
      ? e.clipboardData.items
      : null;
  }
  function getDropImage(e) {
    return e.dataTransfer && e.dataTransfer.files ? e.dataTransfer.files : null;
  }
  return {
    outputRule: function(root) {
      utils.each(root.getNodesByTagName("img"), function(n) {
        if (/\b(loaderrorclass)|(bloaderrorclass)\b/.test(n.getAttr("class"))) {
          n.parentNode.removeChild(n);
        }
      });
      utils.each(root.getNodesByTagName("p"), function(n) {
        if (/\bloadpara\b/.test(n.getAttr("class"))) {
          n.parentNode.removeChild(n);
        }
      });
    },
    bindEvents: {
      defaultOptions: {
        //默认间隔时间
        enableDragUpload: true,
        enablePasteUpload: true
      },
      //插入粘贴板的图片,拖放插入图片
      ready: function(e) {
        var me = this;
        if (window.FormData && window.FileReader) {
          var handler = function(e) {
            var hasImg = false,
              items;
            //获取粘贴板文件列表或者拖放文件列表
            items = e.type == "paste" ? getPasteImage(e) : getDropImage(e);
            if (items) {
              var len = items.length,
                file;
              while (len--) {
                file = items[len];
                if (file.getAsFile) file = file.getAsFile();
                if (file && file.size > 0) {
                  sendAndInsertFile(file, me);
                  hasImg = true;
                }
              }
              hasImg && e.preventDefault();
            }
          };
          if (me.getOpt("enablePasteUpload") !== false) {
            domUtils.on(me.body, "paste ", handler);
          }
          if (me.getOpt("enableDragUpload") !== false) {
            domUtils.on(me.body, "drop", handler);
            //取消拖放图片时出现的文字光标位置提示
            domUtils.on(me.body, "dragover", function(e) {
              if (e.dataTransfer.types[0] == "Files") {
                e.preventDefault();
              }
            });
          } else {
            if (browser.gecko) {
              domUtils.on(me.body, "drop", function(e) {
                if (getDropImage(e)) {
                  e.preventDefault();
                }
              });
            }
          }
          //设置loading的样式
          utils.cssRule(
            "loading",
            ".loadingclass{display:inline-block;cursor:default;background: url('" +
              this.options.themePath +
              this.options.theme +
              "/images/loading.gif') no-repeat center center transparent;border:1px solid #cccccc;margin-left:1px;height: 22px;width: 22px;}\n" +
              ".loaderrorclass{display:inline-block;cursor:default;background: url('" +
              this.options.themePath +
              this.options.theme +
              "/images/loaderror.png') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;" +
              "}",
            this.document
          );
        }
      }
    }
  };
});
// plugins/autosave.js
UE.plugin.register("autosave", function() {
  var me = this,
    //无限循环保护
    lastSaveTime = new Date(),
    //最小保存间隔时间
    MIN_TIME = 20,
    //auto save key
    saveKey = null;
  function save(editor) {
    var saveData;
    if (new Date() - lastSaveTime < MIN_TIME) {
      return;
    }
    if (!editor.hasContents()) {
      //这里不能调用命令来删除, 会造成事件死循环
      saveKey && me.removePreferences(saveKey);
      return;
    }
    lastSaveTime = new Date();
    editor._saveFlag = null;
    saveData = me.body.innerHTML;
    if (
      editor.fireEvent("beforeautosave", {
        content: saveData
      }) === false
    ) {
      return;
    }
    me.setPreferences(saveKey, saveData);
    editor.fireEvent("afterautosave", {
      content: saveData
    });
  }
  return {
    defaultOptions: {
      //默认间隔时间
      saveInterval: 500,
      enableAutoSave: true
    },
    bindEvents: {
      ready: function() {
        var _suffix = "-drafts-data",
          key = null;
        if (me.key) {
          key = me.key + _suffix;
        } else {
          key = (me.container.parentNode.id || "ue-common") + _suffix;
        }
        //页面地址+编辑器ID 保持唯一
        saveKey =
          (location.protocol + location.host + location.pathname).replace(
            /[.:\/]/g,
            "_"
          ) + key;
      },
      contentchange: function() {
        if (!me.getOpt("enableAutoSave")) {
          return;
        }
        if (!saveKey) {
          return;
        }
        if (me._saveFlag) {
          window.clearTimeout(me._saveFlag);
        }
        if (me.options.saveInterval > 0) {
          me._saveFlag = window.setTimeout(function() {
            save(me);
          }, me.options.saveInterval);
        } else {
          save(me);
        }
      }
    },
    commands: {
      clearlocaldata: {
        execCommand: function(cmd, name) {
          if (saveKey && me.getPreferences(saveKey)) {
            me.removePreferences(saveKey);
          }
        },
        notNeedUndo: true,
        ignoreContentChange: true
      },
      getlocaldata: {
        execCommand: function(cmd, name) {
          return saveKey ? me.getPreferences(saveKey) || "" : "";
        },
        notNeedUndo: true,
        ignoreContentChange: true
      },
      drafts: {
        execCommand: function(cmd, name) {
          if (saveKey) {
            me.body.innerHTML =
              me.getPreferences(saveKey) || "" + domUtils.fillHtml + "
";
            me.focus(true);
          }
        },
        queryCommandState: function() {
          return saveKey ? (me.getPreferences(saveKey) === null ? -1 : 0) : -1;
        },
        notNeedUndo: true,
        ignoreContentChange: true
      }
    }
  };
});
// plugins/charts.js
UE.plugin.register("charts", function() {
  var me = this;
  return {
    bindEvents: {
      chartserror: function() {}
    },
    commands: {
      charts: {
        execCommand: function(cmd, data) {
          var tableNode = domUtils.findParentByTagName(
            this.selection.getRange().startContainer,
            "table",
            true
          ),
            flagText = [],
            config = {};
          if (!tableNode) {
            return false;
          }
          if (!validData(tableNode)) {
            me.fireEvent("chartserror");
            return false;
          }
          config.title = data.title || "";
          config.subTitle = data.subTitle || "";
          config.xTitle = data.xTitle || "";
          config.yTitle = data.yTitle || "";
          config.suffix = data.suffix || "";
          config.tip = data.tip || "";
          //数据对齐方式
          config.dataFormat = data.tableDataFormat || "";
          //图表类型
          config.chartType = data.chartType || 0;
          for (var key in config) {
            if (!config.hasOwnProperty(key)) {
              continue;
            }
            flagText.push(key + ":" + config[key]);
          }
          tableNode.setAttribute("data-chart", flagText.join(";"));
          domUtils.addClass(tableNode, "edui-charts-table");
        },
        queryCommandState: function(cmd, name) {
          var tableNode = domUtils.findParentByTagName(
            this.selection.getRange().startContainer,
            "table",
            true
          );
          return tableNode && validData(tableNode) ? 0 : -1;
        }
      }
    },
    inputRule: function(root) {
      utils.each(root.getNodesByTagName("table"), function(tableNode) {
        if (tableNode.getAttr("data-chart") !== undefined) {
          tableNode.setAttr("style");
        }
      });
    },
    outputRule: function(root) {
      utils.each(root.getNodesByTagName("table"), function(tableNode) {
        if (tableNode.getAttr("data-chart") !== undefined) {
          tableNode.setAttr("style", "display: none;");
        }
      });
    }
  };
  function validData(table) {
    var firstRows = null,
      cellCount = 0;
    //行数不够
    if (table.rows.length < 2) {
      return false;
    }
    //列数不够
    if (table.rows[0].cells.length < 2) {
      return false;
    }
    //第一行所有cell必须是th
    firstRows = table.rows[0].cells;
    cellCount = firstRows.length;
    for (var i = 0, cell; (cell = firstRows[i]); i++) {
      if (cell.tagName.toLowerCase() !== "th") {
        return false;
      }
    }
    for (var i = 1, row; (row = table.rows[i]); i++) {
      //每行单元格数不匹配, 返回false
      if (row.cells.length != cellCount) {
        return false;
      }
      //第一列不是th也返回false
      if (row.cells[0].tagName.toLowerCase() !== "th") {
        return false;
      }
      for (var j = 1, cell; (cell = row.cells[j]); j++) {
        var value = utils.trim(cell.innerText || cell.textContent || "");
        value = value
          .replace(new RegExp(UE.dom.domUtils.fillChar, "g"), "")
          .replace(/^\s+|\s+$/g, "");
        //必须是数字
        if (!/^\d*\.?\d+$/.test(value)) {
          return false;
        }
      }
    }
    return true;
  }
});
// plugins/section.js
/**
 * 目录大纲支持插件
 * @file
 * @since 1.3.0
 */
UE.plugin.register("section", function() {
  /* 目录节点对象 */
  function Section(option) {
    this.tag = "";
    (this.level = -1), (this.dom = null);
    this.nextSection = null;
    this.previousSection = null;
    this.parentSection = null;
    this.startAddress = [];
    this.endAddress = [];
    this.children = [];
  }
  function getSection(option) {
    var section = new Section();
    return utils.extend(section, option);
  }
  function getNodeFromAddress(startAddress, root) {
    var current = root;
    for (var i = 0; i < startAddress.length; i++) {
      if (!current.childNodes) return null;
      current = current.childNodes[startAddress[i]];
    }
    return current;
  }
  var me = this;
  return {
    bindMultiEvents: {
      type: "aftersetcontent afterscencerestore",
      handler: function() {
        me.fireEvent("updateSections");
      }
    },
    bindEvents: {
      /* 初始化、拖拽、粘贴、执行setcontent之后 */
      ready: function() {
        me.fireEvent("updateSections");
        domUtils.on(me.body, "drop paste", function() {
          me.fireEvent("updateSections");
        });
      },
      /* 执行paragraph命令之后 */
      afterexeccommand: function(type, cmd) {
        if (cmd == "paragraph") {
          me.fireEvent("updateSections");
        }
      },
      /* 部分键盘操作,触发updateSections事件 */
      keyup: function(type, e) {
        var me = this,
          range = me.selection.getRange();
        if (range.collapsed != true) {
          me.fireEvent("updateSections");
        } else {
          var keyCode = e.keyCode || e.which;
          if (keyCode == 13 || keyCode == 8 || keyCode == 46) {
            me.fireEvent("updateSections");
          }
        }
      }
    },
    commands: {
      getsections: {
        execCommand: function(cmd, levels) {
          var levelFn = levels || ["h1", "h2", "h3", "h4", "h5", "h6"];
          for (var i = 0; i < levelFn.length; i++) {
            if (typeof levelFn[i] == "string") {
              levelFn[i] = (function(fn) {
                return function(node) {
                  return node.tagName == fn.toUpperCase();
                };
              })(levelFn[i]);
            } else if (typeof levelFn[i] != "function") {
              levelFn[i] = function(node) {
                return null;
              };
            }
          }
          function getSectionLevel(node) {
            for (var i = 0; i < levelFn.length; i++) {
              if (levelFn[i](node)) return i;
            }
            return -1;
          }
          var me = this,
            Directory = getSection({ level: -1, title: "root" }),
            previous = Directory;
          function traversal(node, Directory) {
            var level,
              tmpSection = null,
              parent,
              child,
              children = node.childNodes;
            for (var i = 0, len = children.length; i < len; i++) {
              child = children[i];
              level = getSectionLevel(child);
              if (level >= 0) {
                var address = me.selection
                  .getRange()
                  .selectNode(child)
                  .createAddress(true).startAddress,
                  current = getSection({
                    tag: child.tagName,
                    title: child.innerText || child.textContent || "",
                    level: level,
                    dom: child,
                    startAddress: utils.clone(address, []),
                    endAddress: utils.clone(address, []),
                    children: []
                  });
                previous.nextSection = current;
                current.previousSection = previous;
                parent = previous;
                while (level <= parent.level) {
                  parent = parent.parentSection;
                }
                current.parentSection = parent;
                parent.children.push(current);
                tmpSection = previous = current;
              } else {
                child.nodeType === 1 && traversal(child, Directory);
                tmpSection &&
                  tmpSection.endAddress[tmpSection.endAddress.length - 1]++;
              }
            }
          }
          traversal(me.body, Directory);
          return Directory;
        },
        notNeedUndo: true
      },
      movesection: {
        execCommand: function(cmd, sourceSection, targetSection, isAfter) {
          var me = this,
            targetAddress,
            target;
          if (!sourceSection || !targetSection || targetSection.level == -1)
            return;
          targetAddress = isAfter
            ? targetSection.endAddress
            : targetSection.startAddress;
          target = getNodeFromAddress(targetAddress, me.body);
          /* 判断目标地址是否被源章节包含 */
          if (
            !targetAddress ||
            !target ||
            isContainsAddress(
              sourceSection.startAddress,
              sourceSection.endAddress,
              targetAddress
            )
          )
            return;
          var startNode = getNodeFromAddress(
            sourceSection.startAddress,
            me.body
          ),
            endNode = getNodeFromAddress(sourceSection.endAddress, me.body),
            current,
            nextNode;
          if (isAfter) {
            current = endNode;
            while (
              current &&
              !(
                domUtils.getPosition(startNode, current) &
                domUtils.POSITION_FOLLOWING
              )
            ) {
              nextNode = current.previousSibling;
              domUtils.insertAfter(target, current);
              if (current == startNode) break;
              current = nextNode;
            }
          } else {
            current = startNode;
            while (
              current &&
              !(
                domUtils.getPosition(current, endNode) &
                domUtils.POSITION_FOLLOWING
              )
            ) {
              nextNode = current.nextSibling;
              target.parentNode.insertBefore(current, target);
              if (current == endNode) break;
              current = nextNode;
            }
          }
          me.fireEvent("updateSections");
          /* 获取地址的包含关系 */
          function isContainsAddress(startAddress, endAddress, addressTarget) {
            var isAfterStartAddress = false,
              isBeforeEndAddress = false;
            for (var i = 0; i < startAddress.length; i++) {
              if (i >= addressTarget.length) break;
              if (addressTarget[i] > startAddress[i]) {
                isAfterStartAddress = true;
                break;
              } else if (addressTarget[i] < startAddress[i]) {
                break;
              }
            }
            for (var i = 0; i < endAddress.length; i++) {
              if (i >= addressTarget.length) break;
              if (addressTarget[i] < startAddress[i]) {
                isBeforeEndAddress = true;
                break;
              } else if (addressTarget[i] > startAddress[i]) {
                break;
              }
            }
            return isAfterStartAddress && isBeforeEndAddress;
          }
        }
      },
      deletesection: {
        execCommand: function(cmd, section, keepChildren) {
          var me = this;
          if (!section) return;
          function getNodeFromAddress(startAddress) {
            var current = me.body;
            for (var i = 0; i < startAddress.length; i++) {
              if (!current.childNodes) return null;
              current = current.childNodes[startAddress[i]];
            }
            return current;
          }
          var startNode = getNodeFromAddress(section.startAddress),
            endNode = getNodeFromAddress(section.endAddress),
            current = startNode,
            nextNode;
          if (!keepChildren) {
            while (
              current &&
              domUtils.inDoc(endNode, me.document) &&
              !(
                domUtils.getPosition(current, endNode) &
                domUtils.POSITION_FOLLOWING
              )
            ) {
              nextNode = current.nextSibling;
              domUtils.remove(current);
              current = nextNode;
            }
          } else {
            domUtils.remove(current);
          }
          me.fireEvent("updateSections");
        }
      },
      selectsection: {
        execCommand: function(cmd, section) {
          if (!section && !section.dom) return false;
          var me = this,
            range = me.selection.getRange(),
            address = {
              startAddress: utils.clone(section.startAddress, []),
              endAddress: utils.clone(section.endAddress, [])
            };
          address.endAddress[address.endAddress.length - 1]++;
          range.moveToAddress(address).select().scrollToView();
          return true;
        },
        notNeedUndo: true
      },
      scrolltosection: {
        execCommand: function(cmd, section) {
          if (!section && !section.dom) return false;
          var me = this,
            range = me.selection.getRange(),
            address = {
              startAddress: section.startAddress,
              endAddress: section.endAddress
            };
          address.endAddress[address.endAddress.length - 1]++;
          range.moveToAddress(address).scrollToView();
          return true;
        },
        notNeedUndo: true
      }
    }
  };
});
// plugins/simpleupload.js
/**
 * @description
 * 简单上传:点击按钮,直接选择文件上传
 * @author Jinqn
 * @date 2014-03-31
 */
UE.plugin.register("simpleupload", function() {
  var me = this,
    isLoaded = false,
    containerBtn;
  function initUploadBtn() {
    var w = containerBtn.offsetWidth || 20,
      h = containerBtn.offsetHeight || 20,
      btnIframe = document.createElement("iframe"),
      btnStyle =
        "display:block;width:" +
        w +
        "px;height:" +
        h +
        "px;overflow:hidden;border:0;margin:0;padding:0;position:absolute;top:0;left:0;filter:alpha(opacity=0);-moz-opacity:0;-khtml-opacity: 0;opacity: 0;cursor:pointer;";
    domUtils.on(btnIframe, "load", function() {
      var timestrap = (+new Date()).toString(36),
        wrapper,
        btnIframeDoc,
        btnIframeBody;
      btnIframeDoc =
        btnIframe.contentDocument || btnIframe.contentWindow.document;
      btnIframeBody = btnIframeDoc.body;
      wrapper = btnIframeDoc.createElement("div");
      wrapper.innerHTML =
        '" +
        '';
      wrapper.className = "edui-" + me.options.theme;
      wrapper.id = me.ui.id + "_iframeupload";
      btnIframeBody.style.cssText = btnStyle;
      btnIframeBody.style.width = w + "px";
      btnIframeBody.style.height = h + "px";
      btnIframeBody.appendChild(wrapper);
      if (btnIframeBody.parentNode) {
        btnIframeBody.parentNode.style.width = w + "px";
        btnIframeBody.parentNode.style.height = w + "px";
      }
      var form = btnIframeDoc.getElementById("edui_form_" + timestrap);
      var input = btnIframeDoc.getElementById("edui_input_" + timestrap);
      var iframe = btnIframeDoc.getElementById("edui_iframe_" + timestrap);
      domUtils.on(input, "change", function() {
        if (!input.value) return;
        var loadingId = "loading_" + (+new Date()).toString(36);
        var params =
          utils.serializeParam(me.queryCommandValue("serverparam")) || "";
        var imageActionUrl = me.getActionUrl(me.getOpt("imageActionName"));
        var allowFiles = me.getOpt("imageAllowFiles");
        me.focus();
        me.execCommand(
          "inserthtml",
          '' +
              '' +
              title +
              " " +
              "
";
          }
          me.execCommand("insertHtml", html);
          me.fireEvent("afterinsertfile", filelist);
        }
      }
    }
  };
});
// plugins/xssFilter.js
/**
 * @file xssFilter.js
 * @desc xss过滤器
 * @author robbenmu
 */
UE.plugins.xssFilter = function() {
	var config = UEDITOR_CONFIG;
	var whitList = config.whitList;
	function filter(node) {
		var tagName = node.tagName;
		var attrs = node.attrs;
		if (!whitList.hasOwnProperty(tagName)) {
			node.parentNode.removeChild(node);
			return false;
		}
		UE.utils.each(attrs, function (val, key) {
			if (whitList[tagName].indexOf(key) === -1) {
				node.setAttr(key);
			}
		});
	}
	// 添加inserthtml\paste等操作用的过滤规则
	if (whitList && config.xssFilterRules) {
		this.options.filterRules = function () {
			var result = {};
			UE.utils.each(whitList, function(val, key) {
				result[key] = function (node) {
					return filter(node);
				};
			});
			return result;
		}();
	}
	var tagList = [];
	UE.utils.each(whitList, function (val, key) {
		tagList.push(key);
	});
	// 添加input过滤规则
	//
	if (whitList && config.inputXssFilter) {
		this.addInputRule(function (root) {
			root.traversal(function(node) {
				if (node.type !== 'element') {
					return false;
				}
				filter(node);
			});
		});
	}
	// 添加output过滤规则
	//
	if (whitList && config.outputXssFilter) {
		this.addOutputRule(function (root) {
			root.traversal(function(node) {
				if (node.type !== 'element') {
					return false;
				}
				filter(node);
			});
		});
	}
};
// ui/ui.js
var baidu = baidu || {};
baidu.editor = baidu.editor || {};
UE.ui = baidu.editor.ui = {};
// ui/uiutils.js
;(function() {
  var browser = baidu.editor.browser,
    domUtils = baidu.editor.dom.domUtils;
  var magic = "$EDITORUI";
  var root = (window[magic] = {});
  var uidMagic = "ID" + magic;
  var uidCount = 0;
  var uiUtils = (baidu.editor.ui.uiUtils = {
    uid: function(obj) {
      return obj ? obj[uidMagic] || (obj[uidMagic] = ++uidCount) : ++uidCount;
    },
    hook: function(fn, callback) {
      var dg;
      if (fn && fn._callbacks) {
        dg = fn;
      } else {
        dg = function() {
          var q;
          if (fn) {
            q = fn.apply(this, arguments);
          }
          var callbacks = dg._callbacks;
          var k = callbacks.length;
          while (k--) {
            var r = callbacks[k].apply(this, arguments);
            if (q === undefined) {
              q = r;
            }
          }
          return q;
        };
        dg._callbacks = [];
      }
      dg._callbacks.push(callback);
      return dg;
    },
    createElementByHtml: function(html) {
      var el = document.createElement("div");
      el.innerHTML = html;
      el = el.firstChild;
      el.parentNode.removeChild(el);
      return el;
    },
    getViewportElement: function() {
      return browser.ie && browser.quirks
        ? document.body
        : document.documentElement;
    },
    getClientRect: function(element) {
      var bcr;
      //trace  IE6下在控制编辑器显隐时可能会报错,catch一下
      try {
        bcr = element.getBoundingClientRect();
      } catch (e) {
        bcr = { left: 0, top: 0, height: 0, width: 0 };
      }
      var rect = {
        left: Math.round(bcr.left),
        top: Math.round(bcr.top),
        height: Math.round(bcr.bottom - bcr.top),
        width: Math.round(bcr.right - bcr.left)
      };
      var doc;
      while (
        (doc = element.ownerDocument) !== document &&
        (element = domUtils.getWindow(doc).frameElement)
      ) {
        bcr = element.getBoundingClientRect();
        rect.left += bcr.left;
        rect.top += bcr.top;
      }
      rect.bottom = rect.top + rect.height;
      rect.right = rect.left + rect.width;
      return rect;
    },
    getViewportRect: function() {
      var viewportEl = uiUtils.getViewportElement();
      var width = (window.innerWidth || viewportEl.clientWidth) | 0;
      var height = (window.innerHeight || viewportEl.clientHeight) | 0;
      return {
        left: 0,
        top: 0,
        height: height,
        width: width,
        bottom: height,
        right: width
      };
    },
    setViewportOffset: function(element, offset) {
      var rect;
      var fixedLayer = uiUtils.getFixedLayer();
      if (element.parentNode === fixedLayer) {
        element.style.left = offset.left + "px";
        element.style.top = offset.top + "px";
      } else {
        domUtils.setViewportOffset(element, offset);
      }
    },
    getEventOffset: function(evt) {
      var el = evt.target || evt.srcElement;
      var rect = uiUtils.getClientRect(el);
      var offset = uiUtils.getViewportOffsetByEvent(evt);
      return {
        left: offset.left - rect.left,
        top: offset.top - rect.top
      };
    },
    getViewportOffsetByEvent: function(evt) {
      var el = evt.target || evt.srcElement;
      var frameEl = domUtils.getWindow(el).frameElement;
      var offset = {
        left: evt.clientX,
        top: evt.clientY
      };
      if (frameEl && el.ownerDocument !== document) {
        var rect = uiUtils.getClientRect(frameEl);
        offset.left += rect.left;
        offset.top += rect.top;
      }
      return offset;
    },
    setGlobal: function(id, obj) {
      root[id] = obj;
      return magic + '["' + id + '"]';
    },
    unsetGlobal: function(id) {
      delete root[id];
    },
    copyAttributes: function(tgt, src) {
      var attributes = src.attributes;
      var k = attributes.length;
      while (k--) {
        var attrNode = attributes[k];
        if (
          attrNode.nodeName != "style" &&
          attrNode.nodeName != "class" &&
          (!browser.ie || attrNode.specified)
        ) {
          tgt.setAttribute(attrNode.nodeName, attrNode.nodeValue);
        }
      }
      if (src.className) {
        domUtils.addClass(tgt, src.className);
      }
      if (src.style.cssText) {
        tgt.style.cssText += ";" + src.style.cssText;
      }
    },
    removeStyle: function(el, styleName) {
      if (el.style.removeProperty) {
        el.style.removeProperty(styleName);
      } else if (el.style.removeAttribute) {
        el.style.removeAttribute(styleName);
      } else throw "";
    },
    contains: function(elA, elB) {
      return (
        elA &&
        elB &&
        (elA === elB
          ? false
          : elA.contains
            ? elA.contains(elB)
            : elA.compareDocumentPosition(elB) & 16)
      );
    },
    startDrag: function(evt, callbacks, doc) {
      var doc = doc || document;
      var startX = evt.clientX;
      var startY = evt.clientY;
      function handleMouseMove(evt) {
        var x = evt.clientX - startX;
        var y = evt.clientY - startY;
        callbacks.ondragmove(x, y, evt);
        if (evt.stopPropagation) {
          evt.stopPropagation();
        } else {
          evt.cancelBubble = true;
        }
      }
      if (doc.addEventListener) {
        function handleMouseUp(evt) {
          doc.removeEventListener("mousemove", handleMouseMove, true);
          doc.removeEventListener("mouseup", handleMouseUp, true);
          window.removeEventListener("mouseup", handleMouseUp, true);
          callbacks.ondragstop();
        }
        doc.addEventListener("mousemove", handleMouseMove, true);
        doc.addEventListener("mouseup", handleMouseUp, true);
        window.addEventListener("mouseup", handleMouseUp, true);
        evt.preventDefault();
      } else {
        var elm = evt.srcElement;
        elm.setCapture();
        function releaseCaptrue() {
          elm.releaseCapture();
          elm.detachEvent("onmousemove", handleMouseMove);
          elm.detachEvent("onmouseup", releaseCaptrue);
          elm.detachEvent("onlosecaptrue", releaseCaptrue);
          callbacks.ondragstop();
        }
        elm.attachEvent("onmousemove", handleMouseMove);
        elm.attachEvent("onmouseup", releaseCaptrue);
        elm.attachEvent("onlosecaptrue", releaseCaptrue);
        evt.returnValue = false;
      }
      callbacks.ondragstart();
    },
    getFixedLayer: function() {
      var layer = document.getElementById("edui_fixedlayer");
      if (layer == null) {
        layer = document.createElement("div");
        layer.id = "edui_fixedlayer";
        document.body.appendChild(layer);
        if (browser.ie && browser.version <= 8) {
          layer.style.position = "absolute";
          bindFixedLayer();
          setTimeout(updateFixedOffset);
        } else {
          layer.style.position = "fixed";
        }
        layer.style.left = "0";
        layer.style.top = "0";
        layer.style.width = "0";
        layer.style.height = "0";
      }
      return layer;
    },
    makeUnselectable: function(element) {
      if (browser.opera || (browser.ie && browser.version < 9)) {
        element.unselectable = "on";
        if (element.hasChildNodes()) {
          for (var i = 0; i < element.childNodes.length; i++) {
            if (element.childNodes[i].nodeType == 1) {
              uiUtils.makeUnselectable(element.childNodes[i]);
            }
          }
        }
      } else {
        if (element.style.MozUserSelect !== undefined) {
          element.style.MozUserSelect = "none";
        } else if (element.style.WebkitUserSelect !== undefined) {
          element.style.WebkitUserSelect = "none";
        } else if (element.style.KhtmlUserSelect !== undefined) {
          element.style.KhtmlUserSelect = "none";
        }
      }
    }
  });
  function updateFixedOffset() {
    var layer = document.getElementById("edui_fixedlayer");
    uiUtils.setViewportOffset(layer, {
      left: 0,
      top: 0
    });
    //        layer.style.display = 'none';
    //        layer.style.display = 'block';
    //#trace: 1354
    //        setTimeout(updateFixedOffset);
  }
  function bindFixedLayer(adjOffset) {
    domUtils.on(window, "scroll", updateFixedOffset);
    domUtils.on(
      window,
      "resize",
      baidu.editor.utils.defer(updateFixedOffset, 0, true)
    );
  }
})();
// ui/uibase.js
;(function() {
  var utils = baidu.editor.utils,
    uiUtils = baidu.editor.ui.uiUtils,
    EventBase = baidu.editor.EventBase,
    UIBase = (baidu.editor.ui.UIBase = function() {});
  UIBase.prototype = {
    className: "",
    uiName: "",
    initOptions: function(options) {
      var me = this;
      for (var k in options) {
        me[k] = options[k];
      }
      this.id = this.id || "edui" + uiUtils.uid();
    },
    initUIBase: function() {
      this._globalKey = utils.unhtml(uiUtils.setGlobal(this.id, this));
    },
    render: function(holder) {
      var html = this.renderHtml();
      var el = uiUtils.createElementByHtml(html);
      //by xuheng 给每个node添加class
      var list = domUtils.getElementsByTagName(el, "*");
      var theme = "edui-" + (this.theme || this.editor.options.theme);
      var layer = document.getElementById("edui_fixedlayer");
      for (var i = 0, node; (node = list[i++]); ) {
        domUtils.addClass(node, theme);
      }
      domUtils.addClass(el, theme);
      if (layer) {
        layer.className = "";
        domUtils.addClass(layer, theme);
      }
      var seatEl = this.getDom();
      if (seatEl != null) {
        seatEl.parentNode.replaceChild(el, seatEl);
        uiUtils.copyAttributes(el, seatEl);
      } else {
        if (typeof holder == "string") {
          holder = document.getElementById(holder);
        }
        holder = holder || uiUtils.getFixedLayer();
        domUtils.addClass(holder, theme);
        holder.appendChild(el);
      }
      this.postRender();
    },
    getDom: function(name) {
      if (!name) {
        return document.getElementById(this.id);
      } else {
        return document.getElementById(this.id + "_" + name);
      }
    },
    postRender: function() {
      this.fireEvent("postrender");
    },
    getHtmlTpl: function() {
      return "";
    },
    formatHtml: function(tpl) {
      var prefix = "edui-" + this.uiName;
      return tpl
        .replace(/##/g, this.id)
        .replace(/%%-/g, this.uiName ? prefix + "-" : "")
        .replace(/%%/g, (this.uiName ? prefix : "") + " " + this.className)
        .replace(/\$\$/g, this._globalKey);
    },
    renderHtml: function() {
      return this.formatHtml(this.getHtmlTpl());
    },
    dispose: function() {
      var box = this.getDom();
      if (box) baidu.editor.dom.domUtils.remove(box);
      uiUtils.unsetGlobal(this.id);
    }
  };
  utils.inherits(UIBase, EventBase);
})();
// ui/separator.js
;(function() {
  var utils = baidu.editor.utils,
    UIBase = baidu.editor.ui.UIBase,
    Separator = (baidu.editor.ui.Separator = function(options) {
      this.initOptions(options);
      this.initSeparator();
    });
  Separator.prototype = {
    uiName: "separator",
    initSeparator: function() {
      this.initUIBase();
    },
    getHtmlTpl: function() {
      return '
';
    }
  };
  utils.inherits(Separator, UIBase);
})();
// ui/mask.js
///import core
///import uicore
;(function() {
  var utils = baidu.editor.utils,
    domUtils = baidu.editor.dom.domUtils,
    UIBase = baidu.editor.ui.UIBase,
    uiUtils = baidu.editor.ui.uiUtils;
  var Mask = (baidu.editor.ui.Mask = function(options) {
    this.initOptions(options);
    this.initUIBase();
  });
  Mask.prototype = {
    getHtmlTpl: function() {
      return '
';
    },
    postRender: function() {
      var me = this;
      domUtils.on(window, "resize", function() {
        setTimeout(function() {
          if (!me.isHidden()) {
            me._fill();
          }
        });
      });
    },
    show: function(zIndex) {
      this._fill();
      this.getDom().style.display = "";
      this.getDom().style.zIndex = zIndex;
    },
    hide: function() {
      this.getDom().style.display = "none";
      this.getDom().style.zIndex = "";
    },
    isHidden: function() {
      return this.getDom().style.display == "none";
    },
    _onMouseDown: function() {
      return false;
    },
    _onClick: function(e, target) {
      this.fireEvent("click", e, target);
    },
    _fill: function() {
      var el = this.getDom();
      var vpRect = uiUtils.getViewportRect();
      el.style.width = vpRect.width + "px";
      el.style.height = vpRect.height + "px";
    }
  };
  utils.inherits(Mask, UIBase);
})();
// ui/popup.js
///import core
///import uicore
;(function() {
  var utils = baidu.editor.utils,
    uiUtils = baidu.editor.ui.uiUtils,
    domUtils = baidu.editor.dom.domUtils,
    UIBase = baidu.editor.ui.UIBase,
    Popup = (baidu.editor.ui.Popup = function(options) {
      this.initOptions(options);
      this.initPopup();
    });
  var allPopups = [];
  function closeAllPopup(evt, el) {
    for (var i = 0; i < allPopups.length; i++) {
      var pop = allPopups[i];
      if (!pop.isHidden()) {
        if (pop.queryAutoHide(el) !== false) {
          if (
            evt &&
            /scroll/gi.test(evt.type) &&
            pop.className == "edui-wordpastepop"
          )
            return;
          pop.hide();
        }
      }
    }
    if (allPopups.length) pop.editor.fireEvent("afterhidepop");
  }
  Popup.postHide = closeAllPopup;
  var ANCHOR_CLASSES = [
    "edui-anchor-topleft",
    "edui-anchor-topright",
    "edui-anchor-bottomleft",
    "edui-anchor-bottomright"
  ];
  Popup.prototype = {
    SHADOW_RADIUS: 5,
    content: null,
    _hidden: false,
    autoRender: true,
    canSideLeft: true,
    canSideUp: true,
    initPopup: function() {
      this.initUIBase();
      allPopups.push(this);
    },
    getHtmlTpl: function() {
      return (
        '"
      );
    },
    getContentHtmlTpl: function() {
      if (this.content) {
        if (typeof this.content == "string") {
          return this.content;
        }
        return this.content.renderHtml();
      } else {
        return "";
      }
    },
    _UIBase_postRender: UIBase.prototype.postRender,
    postRender: function() {
      if (this.content instanceof UIBase) {
        this.content.postRender();
      }
      //捕获鼠标滚轮
      if (this.captureWheel && !this.captured) {
        this.captured = true;
        var winHeight =
          (document.documentElement.clientHeight ||
            document.body.clientHeight) - 80,
          _height = this.getDom().offsetHeight,
          _top = uiUtils.getClientRect(this.combox.getDom()).top,
          content = this.getDom("content"),
          ifr = this.getDom("body").getElementsByTagName("iframe"),
          me = this;
        ifr.length && (ifr = ifr[0]);
        while (_top + _height > winHeight) {
          _height -= 30;
        }
        content.style.height = _height + "px";
        //同步更改iframe高度
        ifr && (ifr.style.height = _height + "px");
        //阻止在combox上的鼠标滚轮事件, 防止用户的正常操作被误解
        if (window.XMLHttpRequest) {
          domUtils.on(
            content,
            "onmousewheel" in document.body ? "mousewheel" : "DOMMouseScroll",
            function(e) {
              if (e.preventDefault) {
                e.preventDefault();
              } else {
                e.returnValue = false;
              }
              if (e.wheelDelta) {
                content.scrollTop -= e.wheelDelta / 120 * 60;
              } else {
                content.scrollTop -= e.detail / -3 * 60;
              }
            }
          );
        } else {
          //ie6
          domUtils.on(this.getDom(), "mousewheel", function(e) {
            e.returnValue = false;
            me.getDom("content").scrollTop -= e.wheelDelta / 120 * 60;
          });
        }
      }
      this.fireEvent("postRenderAfter");
      this.hide(true);
      this._UIBase_postRender();
    },
    _doAutoRender: function() {
      if (!this.getDom() && this.autoRender) {
        this.render();
      }
    },
    mesureSize: function() {
      var box = this.getDom("content");
      return uiUtils.getClientRect(box);
    },
    fitSize: function() {
      if (this.captureWheel && this.sized) {
        return this.__size;
      }
      this.sized = true;
      var popBodyEl = this.getDom("body");
      popBodyEl.style.width = "";
      popBodyEl.style.height = "";
      var size = this.mesureSize();
      if (this.captureWheel) {
        popBodyEl.style.width = -(-20 - size.width) + "px";
        var height = parseInt(this.getDom("content").style.height, 10);
        !window.isNaN(height) && (size.height = height);
      } else {
        popBodyEl.style.width = size.width + "px";
      }
      popBodyEl.style.height = size.height + "px";
      this.__size = size;
      this.captureWheel && (this.getDom("content").style.overflow = "auto");
      return size;
    },
    showAnchor: function(element, hoz) {
      this.showAnchorRect(uiUtils.getClientRect(element), hoz);
    },
    showAnchorRect: function(rect, hoz, adj) {
      this._doAutoRender();
      var vpRect = uiUtils.getViewportRect();
      this.getDom().style.visibility = "hidden";
      this._show();
      var popSize = this.fitSize();
      var sideLeft, sideUp, left, top;
      if (hoz) {
        sideLeft =
          this.canSideLeft &&
          (rect.right + popSize.width > vpRect.right &&
            rect.left > popSize.width);
        sideUp =
          this.canSideUp &&
          (rect.top + popSize.height > vpRect.bottom &&
            rect.bottom > popSize.height);
        left = sideLeft ? rect.left - popSize.width : rect.right;
        top = sideUp ? rect.bottom - popSize.height : rect.top;
      } else {
        sideLeft =
          this.canSideLeft &&
          (rect.right + popSize.width > vpRect.right &&
            rect.left > popSize.width);
        sideUp =
          this.canSideUp &&
          (rect.top + popSize.height > vpRect.bottom &&
            rect.bottom > popSize.height);
        left = sideLeft ? rect.right - popSize.width : rect.left;
        top = sideUp ? rect.top - popSize.height : rect.bottom;
      }
      var popEl = this.getDom();
      uiUtils.setViewportOffset(popEl, {
        left: left,
        top: top
      });
      domUtils.removeClasses(popEl, ANCHOR_CLASSES);
      popEl.className +=
        " " + ANCHOR_CLASSES[(sideUp ? 1 : 0) * 2 + (sideLeft ? 1 : 0)];
      if (this.editor) {
        popEl.style.zIndex = this.editor.container.style.zIndex * 1 + 10;
        baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex =
          popEl.style.zIndex - 1;
      }
      this.getDom().style.visibility = "visible";
    },
    showAt: function(offset) {
      var left = offset.left;
      var top = offset.top;
      var rect = {
        left: left,
        top: top,
        right: left,
        bottom: top,
        height: 0,
        width: 0
      };
      this.showAnchorRect(rect, false, true);
    },
    _show: function() {
      if (this._hidden) {
        var box = this.getDom();
        box.style.display = "";
        this._hidden = false;
        //                if (box.setActive) {
        //                    box.setActive();
        //                }
        this.fireEvent("show");
      }
    },
    isHidden: function() {
      return this._hidden;
    },
    show: function() {
      this._doAutoRender();
      this._show();
    },
    hide: function(notNofity) {
      if (!this._hidden && this.getDom()) {
        this.getDom().style.display = "none";
        this._hidden = true;
        if (!notNofity) {
          this.fireEvent("hide");
        }
      }
    },
    queryAutoHide: function(el) {
      return !el || !uiUtils.contains(this.getDom(), el);
    }
  };
  utils.inherits(Popup, UIBase);
  domUtils.on(document, "mousedown", function(evt) {
    var el = evt.target || evt.srcElement;
    closeAllPopup(evt, el);
  });
  domUtils.on(window, "scroll", function(evt, el) {
    closeAllPopup(evt, el);
  });
})();
// ui/colorpicker.js
///import core
///import uicore
;(function() {
  var utils = baidu.editor.utils,
    UIBase = baidu.editor.ui.UIBase,
    ColorPicker = (baidu.editor.ui.ColorPicker = function(options) {
      this.initOptions(options);
      this.noColorText = this.noColorText || this.editor.getLang("clearColor");
      this.initUIBase();
    });
  ColorPicker.prototype = {
    getHtmlTpl: function() {
      return genColorPicker(this.noColorText, this.editor);
    },
    _onTableClick: function(evt) {
      var tgt = evt.target || evt.srcElement;
      var color = tgt.getAttribute("data-color");
      if (color) {
        this.fireEvent("pickcolor", color);
      }
    },
    _onTableOver: function(evt) {
      var tgt = evt.target || evt.srcElement;
      var color = tgt.getAttribute("data-color");
      if (color) {
        this.getDom("preview").style.backgroundColor = color;
      }
    },
    _onTableOut: function() {
      this.getDom("preview").style.backgroundColor = "";
    },
    _onPickNoColor: function() {
      this.fireEvent("picknocolor");
    }
  };
  utils.inherits(ColorPicker, UIBase);
  var COLORS = ("ffffff,000000,eeece1,1f497d,4f81bd,c0504d,9bbb59,8064a2,4bacc6,f79646," +
    "f2f2f2,7f7f7f,ddd9c3,c6d9f0,dbe5f1,f2dcdb,ebf1dd,e5e0ec,dbeef3,fdeada," +
    "d8d8d8,595959,c4bd97,8db3e2,b8cce4,e5b9b7,d7e3bc,ccc1d9,b7dde8,fbd5b5," +
    "bfbfbf,3f3f3f,938953,548dd4,95b3d7,d99694,c3d69b,b2a2c7,92cddc,fac08f," +
    "a5a5a5,262626,494429,17365d,366092,953734,76923c,5f497a,31859b,e36c09," +
    "7f7f7f,0c0c0c,1d1b10,0f243e,244061,632423,4f6128,3f3151,205867,974806," +
    "c00000,ff0000,ffc000,ffff00,92d050,00b050,00b0f0,0070c0,002060,7030a0,").split(
    ","
  );
  function genColorPicker(noColorText, editor) {
    var html =
      '' +
      '
' +
      '
' +
      '
' +
      noColorText +
      "
" +
      "
" +
      '
' +
        '
' +
        '
' +
        '
" +
        '
" +
        "
" +
        "
' +
        '
' +
        '
' +
        (this.showIcon ? '
' : "") +
        (this.showText
          ? '
' + this.label + "
"
          : "") +
        "
" +
        "
" +
        "
'
        )
      );
      this.getDom().className += " edui-colorbutton";
    },
    setColor: function(color) {
      this.getDom("colorlump").style.backgroundColor = color;
      this.color = color;
    },
    _onPickColor: function(color) {
      if (this.fireEvent("pickcolor", color) !== false) {
        this.setColor(color);
        this.popup.hide();
      }
    },
    _onPickNoColor: function(color) {
      if (this.fireEvent("picknocolor") !== false) {
        this.popup.hide();
      }
    }
  };
  utils.inherits(ColorButton, SplitButton);
})();
// ui/tablebutton.js
///import core
///import uicore
///import ui/popup.js
///import ui/tablepicker.js
///import ui/splitbutton.js
;(function() {
  var utils = baidu.editor.utils,
    Popup = baidu.editor.ui.Popup,
    TablePicker = baidu.editor.ui.TablePicker,
    SplitButton = baidu.editor.ui.SplitButton,
    TableButton = (baidu.editor.ui.TableButton = function(options) {
      this.initOptions(options);
      this.initTableButton();
    });
  TableButton.prototype = {
    initTableButton: function() {
      var me = this;
      this.popup = new Popup({
        content: new TablePicker({
          editor: me.editor,
          onpicktable: function(t, numCols, numRows) {
            me._onPickTable(numCols, numRows);
          }
        }),
        editor: me.editor
      });
      this.initSplitButton();
    },
    _onPickTable: function(numCols, numRows) {
      if (this.fireEvent("picktable", numCols, numRows) !== false) {
        this.popup.hide();
      }
    }
  };
  utils.inherits(TableButton, SplitButton);
})();
// ui/autotypesetpicker.js
///import core
///import uicore
;(function() {
  var utils = baidu.editor.utils,
    UIBase = baidu.editor.ui.UIBase;
  var AutoTypeSetPicker = (baidu.editor.ui.AutoTypeSetPicker = function(
    options
  ) {
    this.initOptions(options);
    this.initAutoTypeSetPicker();
  });
  AutoTypeSetPicker.prototype = {
    initAutoTypeSetPicker: function() {
      this.initUIBase();
    },
    getHtmlTpl: function() {
      var me = this.editor,
        opt = me.options.autotypeset,
        lang = me.getLang("autoTypeSet");
      var textAlignInputName = "textAlignValue" + me.uid,
        imageBlockInputName = "imageBlockLineValue" + me.uid,
        symbolConverInputName = "symbolConverValue" + me.uid;
      return (
        '"
      );
    },
    _UIBase_render: UIBase.prototype.render
  };
  utils.inherits(AutoTypeSetPicker, UIBase);
})();
// ui/autotypesetbutton.js
///import core
///import uicore
///import ui/popup.js
///import ui/autotypesetpicker.js
///import ui/splitbutton.js
;(function() {
  var utils = baidu.editor.utils,
    Popup = baidu.editor.ui.Popup,
    AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker,
    SplitButton = baidu.editor.ui.SplitButton,
    AutoTypeSetButton = (baidu.editor.ui.AutoTypeSetButton = function(options) {
      this.initOptions(options);
      this.initAutoTypeSetButton();
    });
  function getPara(me) {
    var opt = {},
      cont = me.getDom(),
      editorId = me.editor.uid,
      inputType = null,
      attrName = null,
      ipts = domUtils.getElementsByTagName(cont, "input");
    for (var i = ipts.length - 1, ipt; (ipt = ipts[i--]); ) {
      inputType = ipt.getAttribute("type");
      if (inputType == "checkbox") {
        attrName = ipt.getAttribute("name");
        opt[attrName] && delete opt[attrName];
        if (ipt.checked) {
          var attrValue = document.getElementById(
            attrName + "Value" + editorId
          );
          if (attrValue) {
            if (/input/gi.test(attrValue.tagName)) {
              opt[attrName] = attrValue.value;
            } else {
              var iptChilds = attrValue.getElementsByTagName("input");
              for (
                var j = iptChilds.length - 1, iptchild;
                (iptchild = iptChilds[j--]);
              ) {
                if (iptchild.checked) {
                  opt[attrName] = iptchild.value;
                  break;
                }
              }
            }
          } else {
            opt[attrName] = true;
          }
        } else {
          opt[attrName] = false;
        }
      } else {
        opt[ipt.getAttribute("value")] = ipt.checked;
      }
    }
    var selects = domUtils.getElementsByTagName(cont, "select");
    for (var i = 0, si; (si = selects[i++]); ) {
      var attr = si.getAttribute("name");
      opt[attr] = opt[attr] ? si.value : "";
    }
    utils.extend(me.editor.options.autotypeset, opt);
    me.editor.setPreferences("autotypeset", opt);
  }
  AutoTypeSetButton.prototype = {
    initAutoTypeSetButton: function() {
      var me = this;
      this.popup = new Popup({
        //传入配置参数
        content: new AutoTypeSetPicker({ editor: me.editor }),
        editor: me.editor,
        hide: function() {
          if (!this._hidden && this.getDom()) {
            getPara(this);
            this.getDom().style.display = "none";
            this._hidden = true;
            this.fireEvent("hide");
          }
        }
      });
      var flag = 0;
      this.popup.addListener("postRenderAfter", function() {
        var popupUI = this;
        if (flag) return;
        var cont = this.getDom(),
          btn = cont.getElementsByTagName("button")[0];
        btn.onclick = function() {
          getPara(popupUI);
          me.editor.execCommand("autotypeset");
          popupUI.hide();
        };
        domUtils.on(cont, "click", function(e) {
          var target = e.target || e.srcElement,
            editorId = me.editor.uid;
          if (target && target.tagName == "INPUT") {
            // 点击图片浮动的checkbox,去除对应的radio
            if (
              target.name == "imageBlockLine" ||
              target.name == "textAlign" ||
              target.name == "symbolConver"
            ) {
              var checked = target.checked,
                radioTd = document.getElementById(
                  target.name + "Value" + editorId
                ),
                radios = radioTd.getElementsByTagName("input"),
                defalutSelect = {
                  imageBlockLine: "none",
                  textAlign: "left",
                  symbolConver: "tobdc"
                };
              for (var i = 0; i < radios.length; i++) {
                if (checked) {
                  if (radios[i].value == defalutSelect[target.name]) {
                    radios[i].checked = "checked";
                  }
                } else {
                  radios[i].checked = false;
                }
              }
            }
            // 点击radio,选中对应的checkbox
            if (
              target.name == "imageBlockLineValue" + editorId ||
              target.name == "textAlignValue" + editorId ||
              target.name == "bdc"
            ) {
              var checkboxs = target.parentNode.previousSibling.getElementsByTagName(
                "input"
              );
              checkboxs && (checkboxs[0].checked = true);
            }
            getPara(popupUI);
          }
        });
        flag = 1;
      });
      this.initSplitButton();
    }
  };
  utils.inherits(AutoTypeSetButton, SplitButton);
})();
// ui/cellalignpicker.js
///import core
///import uicore
;(function() {
  var utils = baidu.editor.utils,
    Popup = baidu.editor.ui.Popup,
    Stateful = baidu.editor.ui.Stateful,
    UIBase = baidu.editor.ui.UIBase;
  /**
     * 该参数将新增一个参数: selected, 参数类型为一个Object, 形如{ 'align': 'center', 'valign': 'top' }, 表示单元格的初始
     * 对齐状态为: 竖直居上,水平居中; 其中 align的取值为:'center', 'left', 'right'; valign的取值为: 'top', 'middle', 'bottom'
     * @update 2013/4/2 hancong03@baidu.com
     */
  var CellAlignPicker = (baidu.editor.ui.CellAlignPicker = function(options) {
    this.initOptions(options);
    this.initSelected();
    this.initCellAlignPicker();
  });
  CellAlignPicker.prototype = {
    //初始化选中状态, 该方法将根据传递进来的参数获取到应该选中的对齐方式图标的索引
    initSelected: function() {
      var status = {
        valign: {
          top: 0,
          middle: 1,
          bottom: 2
        },
        align: {
          left: 0,
          center: 1,
          right: 2
        },
        count: 3
      },
        result = -1;
      if (this.selected) {
        this.selectedIndex =
          status.valign[this.selected.valign] * status.count +
          status.align[this.selected.align];
      }
    },
    initCellAlignPicker: function() {
      this.initUIBase();
      this.Stateful_init();
    },
    getHtmlTpl: function() {
      var alignType = ["left", "center", "right"],
        COUNT = 9,
        tempClassName = null,
        tempIndex = -1,
        tmpl = [];
      for (var i = 0; i < COUNT; i++) {
        tempClassName = this.selectedIndex === i
          ? ' class="edui-cellalign-selected" '
          : "";
        tempIndex = i % 3;
        tempIndex === 0 && tmpl.push("");
        tmpl.push(
          '
 ");
      }
      return (
        '"
      );
    },
    getStateDom: function() {
      return this.target;
    },
    _onClick: function(evt) {
      var target = evt.target || evt.srcElement;
      if (/icon/.test(target.className)) {
        this.items[target.parentNode.getAttribute("index")].onclick();
        Popup.postHide(evt);
      }
    },
    _UIBase_render: UIBase.prototype.render
  };
  utils.inherits(CellAlignPicker, UIBase);
  utils.extend(CellAlignPicker.prototype, Stateful, true);
})();
// ui/pastepicker.js
///import core
///import uicore
;(function() {
  var utils = baidu.editor.utils,
    Stateful = baidu.editor.ui.Stateful,
    uiUtils = baidu.editor.ui.uiUtils,
    UIBase = baidu.editor.ui.UIBase;
  var PastePicker = (baidu.editor.ui.PastePicker = function(options) {
    this.initOptions(options);
    this.initPastePicker();
  });
  PastePicker.prototype = {
    initPastePicker: function() {
      this.initUIBase();
      this.Stateful_init();
    },
    getHtmlTpl: function() {
      return (
        '
' +
        '' +
        '
' +
        this.editor.getLang("pasteOpt") +
        "
" +
        '
" +
        "
' +
        buff.join("") +
        "
"
      );
    },
    postRender: function() {
      var box = this.getDom();
      for (var i = 0; i < this.items.length; i++) {
        this.items[i].postRender();
      }
      uiUtils.makeUnselectable(box);
    },
    _onMouseDown: function(e) {
      var target = e.target || e.srcElement,
        tagName = target && target.tagName && target.tagName.toLowerCase();
      if (tagName == "input" || tagName == "object" || tagName == "object") {
        return false;
      }
    }
  };
  utils.inherits(Toolbar, UIBase);
})();
// ui/menu.js
///import core
///import uicore
///import ui\popup.js
///import ui\stateful.js
;(function() {
  var utils = baidu.editor.utils,
    domUtils = baidu.editor.dom.domUtils,
    uiUtils = baidu.editor.ui.uiUtils,
    UIBase = baidu.editor.ui.UIBase,
    Popup = baidu.editor.ui.Popup,
    Stateful = baidu.editor.ui.Stateful,
    CellAlignPicker = baidu.editor.ui.CellAlignPicker,
    Menu = (baidu.editor.ui.Menu = function(options) {
      this.initOptions(options);
      this.initMenu();
    });
  var menuSeparator = {
    renderHtml: function() {
      return '';
    },
    postRender: function() {},
    queryAutoHide: function() {
      return true;
    }
  };
  Menu.prototype = {
    items: null,
    uiName: "menu",
    initMenu: function() {
      this.items = this.items || [];
      this.initPopup();
      this.initItems();
    },
    initItems: function() {
      for (var i = 0; i < this.items.length; i++) {
        var item = this.items[i];
        if (item == "-") {
          this.items[i] = this.getSeparator();
        } else if (!(item instanceof MenuItem)) {
          item.editor = this.editor;
          item.theme = this.editor.options.theme;
          this.items[i] = this.createItem(item);
        }
      }
    },
    getSeparator: function() {
      return menuSeparator;
    },
    createItem: function(item) {
      //新增一个参数menu, 该参数存储了menuItem所对应的menu引用
      item.menu = this;
      return new MenuItem(item);
    },
    _Popup_getContentHtmlTpl: Popup.prototype.getContentHtmlTpl,
    getContentHtmlTpl: function() {
      if (this.items.length == 0) {
        return this._Popup_getContentHtmlTpl();
      }
      var buff = [];
      for (var i = 0; i < this.items.length; i++) {
        var item = this.items[i];
        buff[i] = item.renderHtml();
      }
      return '' + buff.join("") + "
";
    },
    _Popup_postRender: Popup.prototype.postRender,
    postRender: function() {
      var me = this;
      for (var i = 0; i < this.items.length; i++) {
        var item = this.items[i];
        item.ownerMenu = this;
        item.postRender();
      }
      domUtils.on(this.getDom(), "mouseover", function(evt) {
        evt = evt || event;
        var rel = evt.relatedTarget || evt.fromElement;
        var el = me.getDom();
        if (!uiUtils.contains(el, rel) && el !== rel) {
          me.fireEvent("over");
        }
      });
      this._Popup_postRender();
    },
    queryAutoHide: function(el) {
      if (el) {
        if (uiUtils.contains(this.getDom(), el)) {
          return false;
        }
        for (var i = 0; i < this.items.length; i++) {
          var item = this.items[i];
          if (item.queryAutoHide(el) === false) {
            return false;
          }
        }
      }
    },
    clearItems: function() {
      for (var i = 0; i < this.items.length; i++) {
        var item = this.items[i];
        clearTimeout(item._showingTimer);
        clearTimeout(item._closingTimer);
        if (item.subMenu) {
          item.subMenu.destroy();
        }
      }
      this.items = [];
    },
    destroy: function() {
      if (this.getDom()) {
        domUtils.remove(this.getDom());
      }
      this.clearItems();
    },
    dispose: function() {
      this.destroy();
    }
  };
  utils.inherits(Menu, Popup);
  /**
     * @update 2013/04/03 hancong03 新增一个参数menu, 该参数存储了menuItem所对应的menu引用
     * @type {Function}
     */
  var MenuItem = (baidu.editor.ui.MenuItem = function(options) {
    this.initOptions(options);
    this.initUIBase();
    this.Stateful_init();
    if (this.subMenu && !(this.subMenu instanceof Menu)) {
      if (options.className && options.className.indexOf("aligntd") != -1) {
        var me = this;
        //获取单元格对齐初始状态
        this.subMenu.selected = this.editor.queryCommandValue("cellalignment");
        this.subMenu = new Popup({
          content: new CellAlignPicker(this.subMenu),
          parentMenu: me,
          editor: me.editor,
          destroy: function() {
            if (this.getDom()) {
              domUtils.remove(this.getDom());
            }
          }
        });
        this.subMenu.addListener("postRenderAfter", function() {
          domUtils.on(this.getDom(), "mouseover", function() {
            me.addState("opened");
          });
        });
      } else {
        this.subMenu = new Menu(this.subMenu);
      }
    }
  });
  MenuItem.prototype = {
    label: "",
    subMenu: null,
    ownerMenu: null,
    uiName: "menuitem",
    alwalysHoverable: true,
    getHtmlTpl: function() {
      return (
        '' +
        '
' +
        this.renderLabelHtml() +
        "
" +
        "
' +
        '
' +
        '' +
        (this.label || "") +
        "
"
      );
    },
    getStateDom: function() {
      return this.getDom();
    },
    queryAutoHide: function(el) {
      if (this.subMenu && this.hasState("opened")) {
        return this.subMenu.queryAutoHide(el);
      }
    },
    _onClick: function(event, this_) {
      if (this.hasState("disabled")) return;
      if (this.fireEvent("click", event, this_) !== false) {
        if (this.subMenu) {
          this.showSubMenu();
        } else {
          Popup.postHide(event);
        }
      }
    },
    showSubMenu: function() {
      var rect = uiUtils.getClientRect(this.getDom());
      rect.right -= 5;
      rect.left += 2;
      rect.width -= 7;
      rect.top -= 4;
      rect.bottom += 4;
      rect.height += 8;
      this.subMenu.showAnchorRect(rect, true, true);
    },
    hideSubMenu: function() {
      this.subMenu.hide();
    }
  };
  utils.inherits(MenuItem, UIBase);
  utils.extend(MenuItem.prototype, Stateful, true);
})();
// ui/combox.js
///import core
///import uicore
///import ui/menu.js
///import ui/splitbutton.js
;(function() {
  // todo: menu和item提成通用list
  var utils = baidu.editor.utils,
    uiUtils = baidu.editor.ui.uiUtils,
    Menu = baidu.editor.ui.Menu,
    SplitButton = baidu.editor.ui.SplitButton,
    Combox = (baidu.editor.ui.Combox = function(options) {
      this.initOptions(options);
      this.initCombox();
    });
  Combox.prototype = {
    uiName: "combox",
    onbuttonclick: function() {
      this.showPopup();
    },
    initCombox: function() {
      var me = this;
      this.items = this.items || [];
      for (var i = 0; i < this.items.length; i++) {
        var item = this.items[i];
        item.uiName = "listitem";
        item.index = i;
        item.onclick = function() {
          me.selectByIndex(this.index);
        };
      }
      this.popup = new Menu({
        items: this.items,
        uiName: "list",
        editor: this.editor,
        captureWheel: true,
        combox: this
      });
      this.initSplitButton();
    },
    _SplitButton_postRender: SplitButton.prototype.postRender,
    postRender: function() {
      this._SplitButton_postRender();
      this.setLabel(this.label || "");
      this.setValue(this.initValue || "");
    },
    showPopup: function() {
      var rect = uiUtils.getClientRect(this.getDom());
      rect.top += 1;
      rect.bottom -= 1;
      rect.height -= 2;
      this.popup.showAnchorRect(rect);
    },
    getValue: function() {
      return this.value;
    },
    setValue: function(value) {
      var index = this.indexByValue(value);
      if (index != -1) {
        this.selectedIndex = index;
        this.setLabel(this.items[index].label);
        this.value = this.items[index].value;
      } else {
        this.selectedIndex = -1;
        this.setLabel(this.getLabelForUnknowValue(value));
        this.value = value;
      }
    },
    setLabel: function(label) {
      this.getDom("button_body").innerHTML = label;
      this.label = label;
    },
    getLabelForUnknowValue: function(value) {
      return value;
    },
    indexByValue: function(value) {
      for (var i = 0; i < this.items.length; i++) {
        if (value == this.items[i].value) {
          return i;
        }
      }
      return -1;
    },
    getItem: function(index) {
      return this.items[index];
    },
    selectByIndex: function(index) {
      if (
        index < this.items.length &&
        this.fireEvent("select", index) !== false
      ) {
        this.selectedIndex = index;
        this.value = this.items[index].value;
        this.setLabel(this.items[index].label);
      }
    }
  };
  utils.inherits(Combox, SplitButton);
})();
// ui/dialog.js
///import core
///import uicore
///import ui/mask.js
///import ui/button.js
;(function() {
  var utils = baidu.editor.utils,
    domUtils = baidu.editor.dom.domUtils,
    uiUtils = baidu.editor.ui.uiUtils,
    Mask = baidu.editor.ui.Mask,
    UIBase = baidu.editor.ui.UIBase,
    Button = baidu.editor.ui.Button,
    Dialog = (baidu.editor.ui.Dialog = function(options) {
      if (options.name) {
        var name = options.name;
        var cssRules = options.cssRules;
        if (!options.className) {
          options.className = "edui-for-" + name;
        }
        if (cssRules) {
          options.cssRules =
            ".edui-for-" + name + " .edui-dialog-content  {" + cssRules + "}";
        }
      }
      this.initOptions(
        utils.extend(
          {
            autoReset: true,
            draggable: true,
            onok: function() {},
            oncancel: function() {},
            onclose: function(t, ok) {
              return ok ? this.onok() : this.oncancel();
            },
            //是否控制dialog中的scroll事件, 默认为不阻止
            holdScroll: false
          },
          options
        )
      );
      this.initDialog();
    });
  var modalMask;
  var dragMask;
  var activeDialog;
  Dialog.prototype = {
    draggable: false,
    uiName: "dialog",
    initDialog: function() {
      var me = this,
        theme = this.editor.options.theme;
      if (this.cssRules) {
        this.cssRules = ".edui-" + theme + " " + this.cssRules;
        utils.cssRule("edui-customize-" + this.name + "-style", this.cssRules);
      }
      this.initUIBase();
      this.modalMask =
        modalMask ||
        (modalMask = new Mask({
          className: "edui-dialog-modalmask",
          theme: theme,
          onclick: function() {
            activeDialog && activeDialog.close(false);
          }
        }));
      this.dragMask =
        dragMask ||
        (dragMask = new Mask({
          className: "edui-dialog-dragmask",
          theme: theme
        }));
      this.closeButton = new Button({
        className: "edui-dialog-closebutton",
        title: me.closeDialog,
        theme: theme,
        onclick: function() {
          me.close(false);
        }
      });
      this.fullscreen && this.initResizeEvent();
      if (this.buttons) {
        for (var i = 0; i < this.buttons.length; i++) {
          if (!(this.buttons[i] instanceof Button)) {
            this.buttons[i] = new Button(
              utils.extend(
                this.buttons[i],
                {
                  editor: this.editor
                },
                true
              )
            );
          }
        }
      }
    },
    initResizeEvent: function() {
      var me = this;
      domUtils.on(window, "resize", function() {
        if (me._hidden || me._hidden === undefined) {
          return;
        }
        if (me.__resizeTimer) {
          window.clearTimeout(me.__resizeTimer);
        }
        me.__resizeTimer = window.setTimeout(function() {
          me.__resizeTimer = null;
          var dialogWrapNode = me.getDom(),
            contentNode = me.getDom("content"),
            wrapRect = UE.ui.uiUtils.getClientRect(dialogWrapNode),
            contentRect = UE.ui.uiUtils.getClientRect(contentNode),
            vpRect = uiUtils.getViewportRect();
          contentNode.style.width =
            vpRect.width - wrapRect.width + contentRect.width + "px";
          contentNode.style.height =
            vpRect.height - wrapRect.height + contentRect.height + "px";
          dialogWrapNode.style.width = vpRect.width + "px";
          dialogWrapNode.style.height = vpRect.height + "px";
          me.fireEvent("resize");
        }, 100);
      });
    },
    fitSize: function() {
      var popBodyEl = this.getDom("body");
      //            if (!(baidu.editor.browser.ie && baidu.editor.browser.version == 7)) {
      //                uiUtils.removeStyle(popBodyEl, 'width');
      //                uiUtils.removeStyle(popBodyEl, 'height');
      //            }
      var size = this.mesureSize();
      popBodyEl.style.width = size.width + "px";
      popBodyEl.style.height = size.height + "px";
      return size;
    },
    safeSetOffset: function(offset) {
      var me = this;
      var el = me.getDom();
      var vpRect = uiUtils.getViewportRect();
      var rect = uiUtils.getClientRect(el);
      var left = offset.left;
      if (left + rect.width > vpRect.right) {
        left = vpRect.right - rect.width;
      }
      var top = offset.top;
      if (top + rect.height > vpRect.bottom) {
        top = vpRect.bottom - rect.height;
      }
      el.style.left = Math.max(left, 0) + "px";
      el.style.top = Math.max(top, 0) + "px";
    },
    showAtCenter: function() {
      var vpRect = uiUtils.getViewportRect();
      if (!this.fullscreen) {
        this.getDom().style.display = "";
        var popSize = this.fitSize();
        var titleHeight = this.getDom("titlebar").offsetHeight | 0;
        var left = vpRect.width / 2 - popSize.width / 2;
        var top =
          vpRect.height / 2 - (popSize.height - titleHeight) / 2 - titleHeight;
        var popEl = this.getDom();
        this.safeSetOffset({
          left: Math.max(left | 0, 0),
          top: Math.max(top | 0, 0)
        });
        if (!domUtils.hasClass(popEl, "edui-state-centered")) {
          popEl.className += " edui-state-centered";
        }
      } else {
        var dialogWrapNode = this.getDom(),
          contentNode = this.getDom("content");
        dialogWrapNode.style.display = "block";
        var wrapRect = UE.ui.uiUtils.getClientRect(dialogWrapNode),
          contentRect = UE.ui.uiUtils.getClientRect(contentNode);
        dialogWrapNode.style.left = "-100000px";
        contentNode.style.width =
          vpRect.width - wrapRect.width + contentRect.width + "px";
        contentNode.style.height =
          vpRect.height - wrapRect.height + contentRect.height + "px";
        dialogWrapNode.style.width = vpRect.width + "px";
        dialogWrapNode.style.height = vpRect.height + "px";
        dialogWrapNode.style.left = 0;
        //保存环境的overflow值
        this._originalContext = {
          html: {
            overflowX: document.documentElement.style.overflowX,
            overflowY: document.documentElement.style.overflowY
          },
          body: {
            overflowX: document.body.style.overflowX,
            overflowY: document.body.style.overflowY
          }
        };
        document.documentElement.style.overflowX = "hidden";
        document.documentElement.style.overflowY = "hidden";
        document.body.style.overflowX = "hidden";
        document.body.style.overflowY = "hidden";
      }
      this._show();
    },
    getContentHtml: function() {
      var contentHtml = "";
      if (typeof this.content == "string") {
        contentHtml = this.content;
      } else if (this.iframeUrl) {
        contentHtml =
          '' +
        '
' +
        '
' +
        '
' +
        '' +
        (this.title || "") +
        " " +
        "
" +
        this.closeButton.renderHtml() +
        "
" +
        '
' +
        (this.autoReset ? "" : this.getContentHtml()) +
        "
" +
        footHtml +
        "
' +
        buff +
        "
"
      );
    }
  };
  utils.inherits(ShortCutMenu, UIBase);
  function hideAllMenu(e) {
    var tgt = e.target || e.srcElement,
      cur = domUtils.findParent(
        tgt,
        function(node) {
          return (
            domUtils.hasClass(node, "edui-shortcutmenu") ||
            domUtils.hasClass(node, "edui-popup")
          );
        },
        true
      );
    if (!cur) {
      for (var i = 0, menu; (menu = allMenus[i++]); ) {
        menu.hide();
      }
    }
  }
  domUtils.on(document, "mousedown", function(e) {
    hideAllMenu(e);
  });
  domUtils.on(window, "scroll", function(e) {
    hideAllMenu(e);
  });
})();
// ui/breakline.js
;(function() {
  var utils = baidu.editor.utils,
    UIBase = baidu.editor.ui.UIBase,
    Breakline = (baidu.editor.ui.Breakline = function(options) {
      this.initOptions(options);
      this.initSeparator();
    });
  Breakline.prototype = {
    uiName: "Breakline",
    initSeparator: function() {
      this.initUIBase();
    },
    getHtmlTpl: function() {
      return "' +
        ' 
×
' +
        ' 
' +
        ' 
' +
        ' 
' +
        ' 
' +
        "  
" +
        " 
" +
        "
' + (this.label || "") + "
"
          );
        }
      });
    });
    var ui = new editorui.Combox({
      editor: editor,
      items: items,
      onselect: function(t, index) {
        editor.execCommand("insertcode", this.items[index].value);
      },
      onbuttonclick: function() {
        this.showPopup();
      },
      title: title,
      initValue: title,
      className: "edui-for-insertcode",
      indexByValue: function(value) {
        if (value) {
          for (var i = 0, ci; (ci = this.items[i]); i++) {
            if (ci.value.indexOf(value) != -1) return i;
          }
        }
        return -1;
      }
    });
    editorui.buttons["insertcode"] = ui;
    editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
      if (!uiReady) {
        var state = editor.queryCommandState("insertcode");
        if (state == -1) {
          ui.setDisabled(true);
        } else {
          ui.setDisabled(false);
          var value = editor.queryCommandValue("insertcode");
          if (!value) {
            ui.setValue(title);
            return;
          }
          //trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号
          value && (value = value.replace(/['"]/g, "").split(",")[0]);
          ui.setValue(value);
        }
      }
    });
    return ui;
  };
  editorui.fontfamily = function(editor, list, title) {
    list = editor.options["fontfamily"] || [];
    title =
      editor.options.labelMap["fontfamily"] ||
      editor.getLang("labelMap.fontfamily") ||
      "";
    if (!list.length) return;
    for (var i = 0, ci, items = []; (ci = list[i]); i++) {
      var langLabel = editor.getLang("fontfamily")[ci.name] || "";
      (function(key, val) {
        items.push({
          label: key,
          value: val,
          theme: editor.options.theme,
          renderLabelHtml: function() {
            return (
              '' +
              (this.label || "") +
              "
"
            );
          }
        });
      })(ci.label || langLabel, ci.val);
    }
    var ui = new editorui.Combox({
      editor: editor,
      items: items,
      onselect: function(t, index) {
        editor.execCommand("FontFamily", this.items[index].value);
      },
      onbuttonclick: function() {
        this.showPopup();
      },
      title: title,
      initValue: title,
      className: "edui-for-fontfamily",
      indexByValue: function(value) {
        if (value) {
          for (var i = 0, ci; (ci = this.items[i]); i++) {
            if (ci.value.indexOf(value) != -1) return i;
          }
        }
        return -1;
      }
    });
    editorui.buttons["fontfamily"] = ui;
    editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
      if (!uiReady) {
        var state = editor.queryCommandState("FontFamily");
        if (state == -1) {
          ui.setDisabled(true);
        } else {
          ui.setDisabled(false);
          var value = editor.queryCommandValue("FontFamily");
          //trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号
          value && (value = value.replace(/['"]/g, "").split(",")[0]);
          ui.setValue(value);
        }
      }
    });
    return ui;
  };
  editorui.fontsize = function(editor, list, title) {
    title =
      editor.options.labelMap["fontsize"] ||
      editor.getLang("labelMap.fontsize") ||
      "";
    list = list || editor.options["fontsize"] || [];
    if (!list.length) return;
    var items = [];
    for (var i = 0; i < list.length; i++) {
      var size = list[i] + "px";
      items.push({
        label: size,
        value: size,
        theme: editor.options.theme,
        renderLabelHtml: function() {
          return (
            '' +
            (this.label || "") +
            "
"
          );
        }
      });
    }
    var ui = new editorui.Combox({
      editor: editor,
      items: items,
      title: title,
      initValue: title,
      onselect: function(t, index) {
        editor.execCommand("FontSize", this.items[index].value);
      },
      onbuttonclick: function() {
        this.showPopup();
      },
      className: "edui-for-fontsize"
    });
    editorui.buttons["fontsize"] = ui;
    editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
      if (!uiReady) {
        var state = editor.queryCommandState("FontSize");
        if (state == -1) {
          ui.setDisabled(true);
        } else {
          ui.setDisabled(false);
          ui.setValue(editor.queryCommandValue("FontSize"));
        }
      }
    });
    return ui;
  };
  editorui.paragraph = function(editor, list, title) {
    title =
      editor.options.labelMap["paragraph"] ||
      editor.getLang("labelMap.paragraph") ||
      "";
    list = editor.options["paragraph"] || [];
    if (utils.isEmptyObject(list)) return;
    var items = [];
    for (var i in list) {
      items.push({
        value: i,
        label: list[i] || editor.getLang("paragraph")[i],
        theme: editor.options.theme,
        renderLabelHtml: function() {
          return (
            '' +
            (this.label || "") +
            " 
"
          );
        }
      });
    }
    var ui = new editorui.Combox({
      editor: editor,
      items: items,
      title: title,
      initValue: title,
      className: "edui-for-paragraph",
      onselect: function(t, index) {
        editor.execCommand("Paragraph", this.items[index].value);
      },
      onbuttonclick: function() {
        this.showPopup();
      }
    });
    editorui.buttons["paragraph"] = ui;
    editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
      if (!uiReady) {
        var state = editor.queryCommandState("Paragraph");
        if (state == -1) {
          ui.setDisabled(true);
        } else {
          ui.setDisabled(false);
          var value = editor.queryCommandValue("Paragraph");
          var index = ui.indexByValue(value);
          if (index != -1) {
            ui.setValue(value);
          } else {
            ui.setValue(ui.initValue);
          }
        }
      }
    });
    return ui;
  };
  //自定义标题
  editorui.customstyle = function(editor) {
    var list = editor.options["customstyle"] || [],
      title =
        editor.options.labelMap["customstyle"] ||
        editor.getLang("labelMap.customstyle") ||
        "";
    if (!list.length) return;
    var langCs = editor.getLang("customstyle");
    for (var i = 0, items = [], t; (t = list[i++]); ) {
      (function(t) {
        var ck = {};
        ck.label = t.label ? t.label : langCs[t.name];
        ck.style = t.style;
        ck.className = t.className;
        ck.tag = t.tag;
        items.push({
          label: ck.label,
          value: ck,
          theme: editor.options.theme,
          renderLabelHtml: function() {
            return (
              '' +
              "<" +
              ck.tag +
              " " +
              (ck.className ? ' class="' + ck.className + '"' : "") +
              (ck.style ? ' style="' + ck.style + '"' : "") +
              ">" +
              ck.label +
              "" +
              ck.tag +
              ">" +
              "
"
            );
          }
        });
      })(t);
    }
    var ui = new editorui.Combox({
      editor: editor,
      items: items,
      title: title,
      initValue: title,
      className: "edui-for-customstyle",
      onselect: function(t, index) {
        editor.execCommand("customstyle", this.items[index].value);
      },
      onbuttonclick: function() {
        this.showPopup();
      },
      indexByValue: function(value) {
        for (var i = 0, ti; (ti = this.items[i++]); ) {
          if (ti.label == value) {
            return i - 1;
          }
        }
        return -1;
      }
    });
    editorui.buttons["customstyle"] = ui;
    editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
      if (!uiReady) {
        var state = editor.queryCommandState("customstyle");
        if (state == -1) {
          ui.setDisabled(true);
        } else {
          ui.setDisabled(false);
          var value = editor.queryCommandValue("customstyle");
          var index = ui.indexByValue(value);
          if (index != -1) {
            ui.setValue(value);
          } else {
            ui.setValue(ui.initValue);
          }
        }
      }
    });
    return ui;
  };
  editorui.inserttable = function(editor, iframeUrl, title) {
    title =
      editor.options.labelMap["inserttable"] ||
      editor.getLang("labelMap.inserttable") ||
      "";
    var ui = new editorui.TableButton({
      editor: editor,
      title: title,
      className: "edui-for-inserttable",
      onpicktable: function(t, numCols, numRows) {
        editor.execCommand("InsertTable", {
          numRows: numRows,
          numCols: numCols,
          border: 1
        });
      },
      onbuttonclick: function() {
        this.showPopup();
      }
    });
    editorui.buttons["inserttable"] = ui;
    editor.addListener("selectionchange", function() {
      ui.setDisabled(editor.queryCommandState("inserttable") == -1);
    });
    return ui;
  };
  editorui.lineheight = function(editor) {
    var val = editor.options.lineheight || [];
    if (!val.length) return;
    for (var i = 0, ci, items = []; (ci = val[i++]); ) {
      items.push({
        //todo:写死了
        label: ci,
        value: ci,
        theme: editor.options.theme,
        onclick: function() {
          editor.execCommand("lineheight", this.value);
        }
      });
    }
    var ui = new editorui.MenuButton({
      editor: editor,
      className: "edui-for-lineheight",
      title:
        editor.options.labelMap["lineheight"] ||
          editor.getLang("labelMap.lineheight") ||
          "",
      items: items,
      onbuttonclick: function() {
        var value = editor.queryCommandValue("LineHeight") || this.value;
        editor.execCommand("LineHeight", value);
      }
    });
    editorui.buttons["lineheight"] = ui;
    editor.addListener("selectionchange", function() {
      var state = editor.queryCommandState("LineHeight");
      if (state == -1) {
        ui.setDisabled(true);
      } else {
        ui.setDisabled(false);
        var value = editor.queryCommandValue("LineHeight");
        value && ui.setValue((value + "").replace(/cm/, ""));
        ui.setChecked(state);
      }
    });
    return ui;
  };
  var rowspacings = ["top", "bottom"];
  for (var r = 0, ri; (ri = rowspacings[r++]); ) {
    (function(cmd) {
      editorui["rowspacing" + cmd] = function(editor) {
        var val = editor.options["rowspacing" + cmd] || [];
        if (!val.length) return null;
        for (var i = 0, ci, items = []; (ci = val[i++]); ) {
          items.push({
            label: ci,
            value: ci,
            theme: editor.options.theme,
            onclick: function() {
              editor.execCommand("rowspacing", this.value, cmd);
            }
          });
        }
        var ui = new editorui.MenuButton({
          editor: editor,
          className: "edui-for-rowspacing" + cmd,
          title:
            editor.options.labelMap["rowspacing" + cmd] ||
              editor.getLang("labelMap.rowspacing" + cmd) ||
              "",
          items: items,
          onbuttonclick: function() {
            var value =
              editor.queryCommandValue("rowspacing", cmd) || this.value;
            editor.execCommand("rowspacing", value, cmd);
          }
        });
        editorui.buttons[cmd] = ui;
        editor.addListener("selectionchange", function() {
          var state = editor.queryCommandState("rowspacing", cmd);
          if (state == -1) {
            ui.setDisabled(true);
          } else {
            ui.setDisabled(false);
            var value = editor.queryCommandValue("rowspacing", cmd);
            value && ui.setValue((value + "").replace(/%/, ""));
            ui.setChecked(state);
          }
        });
        return ui;
      };
    })(ri);
  }
  //有序,无序列表
  var lists = ["insertorderedlist", "insertunorderedlist"];
  for (var l = 0, cl; (cl = lists[l++]); ) {
    (function(cmd) {
      editorui[cmd] = function(editor) {
        var vals = editor.options[cmd],
          _onMenuClick = function() {
            editor.execCommand(cmd, this.value);
          },
          items = [];
        for (var i in vals) {
          items.push({
            label: vals[i] || editor.getLang()[cmd][i] || "",
            value: i,
            theme: editor.options.theme,
            onclick: _onMenuClick
          });
        }
        var ui = new editorui.MenuButton({
          editor: editor,
          className: "edui-for-" + cmd,
          title: editor.getLang("labelMap." + cmd) || "",
          items: items,
          onbuttonclick: function() {
            var value = editor.queryCommandValue(cmd) || this.value;
            editor.execCommand(cmd, value);
          }
        });
        editorui.buttons[cmd] = ui;
        editor.addListener("selectionchange", function() {
          var state = editor.queryCommandState(cmd);
          if (state == -1) {
            ui.setDisabled(true);
          } else {
            ui.setDisabled(false);
            var value = editor.queryCommandValue(cmd);
            ui.setValue(value);
            ui.setChecked(state);
          }
        });
        return ui;
      };
    })(cl);
  }
  editorui.fullscreen = function(editor, title) {
    title =
      editor.options.labelMap["fullscreen"] ||
      editor.getLang("labelMap.fullscreen") ||
      "";
    var ui = new editorui.Button({
      className: "edui-for-fullscreen",
      title: title,
      theme: editor.options.theme,
      onclick: function() {
        if (editor.ui) {
          editor.ui.setFullScreen(!editor.ui.isFullScreen());
        }
        this.setChecked(editor.ui.isFullScreen());
      }
    });
    editorui.buttons["fullscreen"] = ui;
    editor.addListener("selectionchange", function() {
      var state = editor.queryCommandState("fullscreen");
      ui.setDisabled(state == -1);
      ui.setChecked(editor.ui.isFullScreen());
    });
    return ui;
  };
  // 表情
  editorui["emotion"] = function(editor, iframeUrl) {
    var cmd = "emotion";
    var ui = new editorui.MultiMenuPop({
      title:
        editor.options.labelMap[cmd] ||
          editor.getLang("labelMap." + cmd + "") ||
          "",
      editor: editor,
      className: "edui-for-" + cmd,
      iframeUrl: editor.ui.mapUrl(
        iframeUrl ||
          (editor.options.iframeUrlMap || {})[cmd] ||
          iframeUrlMap[cmd]
      )
    });
    editorui.buttons[cmd] = ui;
    editor.addListener("selectionchange", function() {
      ui.setDisabled(editor.queryCommandState(cmd) == -1);
    });
    return ui;
  };
  editorui.autotypeset = function(editor) {
    var ui = new editorui.AutoTypeSetButton({
      editor: editor,
      title:
        editor.options.labelMap["autotypeset"] ||
          editor.getLang("labelMap.autotypeset") ||
          "",
      className: "edui-for-autotypeset",
      onbuttonclick: function() {
        editor.execCommand("autotypeset");
      }
    });
    editorui.buttons["autotypeset"] = ui;
    editor.addListener("selectionchange", function() {
      ui.setDisabled(editor.queryCommandState("autotypeset") == -1);
    });
    return ui;
  };
  /* 简单上传插件 */
  editorui["simpleupload"] = function(editor) {
    var name = "simpleupload",
      ui = new editorui.Button({
        className: "edui-for-" + name,
        title:
          editor.options.labelMap[name] ||
            editor.getLang("labelMap." + name) ||
            "",
        onclick: function() {},
        theme: editor.options.theme,
        showText: false
      });
    editorui.buttons[name] = ui;
    editor.addListener("ready", function() {
      var b = ui.getDom("body"),
        iconSpan = b.children[0];
      editor.fireEvent("simpleuploadbtnready", iconSpan);
    });
    editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
      var state = editor.queryCommandState(name);
      if (state == -1) {
        ui.setDisabled(true);
        ui.setChecked(false);
      } else {
        if (!uiReady) {
          ui.setDisabled(false);
          ui.setChecked(state);
        }
      }
    });
    return ui;
  };
})();
// adapter/editor.js
///import core
///commands 全屏
///commandsName FullScreen
///commandsTitle  全屏
;(function() {
  var utils = baidu.editor.utils,
    uiUtils = baidu.editor.ui.uiUtils,
    UIBase = baidu.editor.ui.UIBase,
    domUtils = baidu.editor.dom.domUtils;
  var nodeStack = [];
  function EditorUI(options) {
    this.initOptions(options);
    this.initEditorUI();
  }
  EditorUI.prototype = {
    uiName: "editor",
    initEditorUI: function() {
      this.editor.ui = this;
      this._dialogs = {};
      this.initUIBase();
      this._initToolbars();
      var editor = this.editor,
        me = this;
      editor.addListener("ready", function() {
        //提供getDialog方法
        editor.getDialog = function(name) {
          return editor.ui._dialogs[name + "Dialog"];
        };
        domUtils.on(editor.window, "scroll", function(evt) {
          baidu.editor.ui.Popup.postHide(evt);
        });
        //提供编辑器实时宽高(全屏时宽高不变化)
        editor.ui._actualFrameWidth = editor.options.initialFrameWidth;
        UE.browser.ie &&
          UE.browser.version === 6 &&
          editor.container.ownerDocument.execCommand(
            "BackgroundImageCache",
            false,
            true
          );
        //display bottom-bar label based on config
        if (editor.options.elementPathEnabled) {
          editor.ui.getDom("elementpath").innerHTML =
            '' +
            editor.getLang("elementPathTip") +
            ":
";
        }
        if (editor.options.wordCount) {
          function countFn() {
            setCount(editor, me);
            domUtils.un(editor.document, "click", arguments.callee);
          }
          domUtils.on(editor.document, "click", countFn);
          editor.ui.getDom("wordcount").innerHTML = editor.getLang(
            "wordCountTip"
          );
        }
        editor.ui._scale();
        if (editor.options.scaleEnabled) {
          if (editor.autoHeightEnabled) {
            editor.disableAutoHeight();
          }
          me.enableScale();
        } else {
          me.disableScale();
        }
        if (
          !editor.options.elementPathEnabled &&
          !editor.options.wordCount &&
          !editor.options.scaleEnabled
        ) {
          editor.ui.getDom("elementpath").style.display = "none";
          editor.ui.getDom("wordcount").style.display = "none";
          editor.ui.getDom("scale").style.display = "none";
        }
        if (!editor.selection.isFocus()) return;
        editor.fireEvent("selectionchange", false, true);
      });
      editor.addListener("mousedown", function(t, evt) {
        var el = evt.target || evt.srcElement;
        baidu.editor.ui.Popup.postHide(evt, el);
        baidu.editor.ui.ShortCutMenu.postHide(evt);
      });
      editor.addListener("delcells", function() {
        if (UE.ui["edittip"]) {
          new UE.ui["edittip"](editor);
        }
        editor.getDialog("edittip").open();
      });
      var pastePop,
        isPaste = false,
        timer;
      editor.addListener("afterpaste", function() {
        if (editor.queryCommandState("pasteplain")) return;
        if (baidu.editor.ui.PastePicker) {
          pastePop = new baidu.editor.ui.Popup({
            content: new baidu.editor.ui.PastePicker({ editor: editor }),
            editor: editor,
            className: "edui-wordpastepop"
          });
          pastePop.render();
        }
        isPaste = true;
      });
      editor.addListener("afterinserthtml", function() {
        clearTimeout(timer);
        timer = setTimeout(function() {
          if (pastePop && (isPaste || editor.ui._isTransfer)) {
            if (pastePop.isHidden()) {
              var span = domUtils.createElement(editor.document, "span", {
                style: "line-height:0px;",
                innerHTML: "\ufeff"
              }),
                range = editor.selection.getRange();
              range.insertNode(span);
              var tmp = getDomNode(span, "firstChild", "previousSibling");
              tmp &&
                pastePop.showAnchor(tmp.nodeType == 3 ? tmp.parentNode : tmp);
              domUtils.remove(span);
            } else {
              pastePop.show();
            }
            delete editor.ui._isTransfer;
            isPaste = false;
          }
        }, 200);
      });
      editor.addListener("contextmenu", function(t, evt) {
        baidu.editor.ui.Popup.postHide(evt);
      });
      editor.addListener("keydown", function(t, evt) {
        if (pastePop) pastePop.dispose(evt);
        var keyCode = evt.keyCode || evt.which;
        if (evt.altKey && keyCode == 90) {
          UE.ui.buttons["fullscreen"].onclick();
        }
      });
      editor.addListener("wordcount", function(type) {
        setCount(this, me);
      });
      function setCount(editor, ui) {
        editor.setOpt({
          wordCount: true,
          maximumWords: 10000,
          wordCountMsg:
            editor.options.wordCountMsg || editor.getLang("wordCountMsg"),
          wordOverFlowMsg:
            editor.options.wordOverFlowMsg || editor.getLang("wordOverFlowMsg")
        });
        var opt = editor.options,
          max = opt.maximumWords,
          msg = opt.wordCountMsg,
          errMsg = opt.wordOverFlowMsg,
          countDom = ui.getDom("wordcount");
        if (!opt.wordCount) {
          return;
        }
        var count = editor.getContentLength(true);
        if (count > max) {
          countDom.innerHTML = errMsg;
          editor.fireEvent("wordcountoverflow");
        } else {
          countDom.innerHTML = msg
            .replace("{#leave}", max - count)
            .replace("{#count}", count);
        }
      }
      editor.addListener("selectionchange", function() {
        if (editor.options.elementPathEnabled) {
          me[
            (editor.queryCommandState("elementpath") == -1 ? "dis" : "en") +
              "ableElementPath"
          ]();
        }
        if (editor.options.scaleEnabled) {
          me[
            (editor.queryCommandState("scale") == -1 ? "dis" : "en") +
              "ableScale"
          ]();
        }
      });
      var popup = new baidu.editor.ui.Popup({
        editor: editor,
        content: "",
        className: "edui-bubble",
        _onEditButtonClick: function() {
          this.hide();
          editor.ui._dialogs.linkDialog.open();
        },
        _onImgEditButtonClick: function(name) {
          this.hide();
          editor.ui._dialogs[name] && editor.ui._dialogs[name].open();
        },
        _onImgSetFloat: function(value) {
          this.hide();
          editor.execCommand("imagefloat", value);
        },
        _setIframeAlign: function(value) {
          var frame = popup.anchorEl;
          var newFrame = frame.cloneNode(true);
          switch (value) {
            case -2:
              newFrame.setAttribute("align", "");
              break;
            case -1:
              newFrame.setAttribute("align", "left");
              break;
            case 1:
              newFrame.setAttribute("align", "right");
              break;
          }
          frame.parentNode.insertBefore(newFrame, frame);
          domUtils.remove(frame);
          popup.anchorEl = newFrame;
          popup.showAnchor(popup.anchorEl);
        },
        _updateIframe: function() {
          var frame = (editor._iframe = popup.anchorEl);
          if (domUtils.hasClass(frame, "ueditor_baidumap")) {
            editor.selection.getRange().selectNode(frame).select();
            editor.ui._dialogs.mapDialog.open();
            popup.hide();
          } else {
            editor.ui._dialogs.insertframeDialog.open();
            popup.hide();
          }
        },
        _onRemoveButtonClick: function(cmdName) {
          editor.execCommand(cmdName);
          this.hide();
        },
        queryAutoHide: function(el) {
          if (el && el.ownerDocument == editor.document) {
            if (
              el.tagName.toLowerCase() == "img" ||
              domUtils.findParentByTagName(el, "a", true)
            ) {
              return el !== popup.anchorEl;
            }
          }
          return baidu.editor.ui.Popup.prototype.queryAutoHide.call(this, el);
        }
      });
      popup.render();
      if (editor.options.imagePopup) {
        editor.addListener("mouseover", function(t, evt) {
          evt = evt || window.event;
          var el = evt.target || evt.srcElement;
          if (
            editor.ui._dialogs.insertframeDialog &&
            /iframe/gi.test(el.tagName)
          ) {
            var html = popup.formatHtml(
              "" +
                editor.getLang("property") +
                ': ' +
                editor.getLang("default") +
                '   ' +
                editor.getLang("justifyleft") +
                '   ' +
                editor.getLang("justifyright") +
                "   " +
                ' ' +
                editor.getLang("modify") +
                "  "
            );
            if (html) {
              popup.getDom("content").innerHTML = html;
              popup.anchorEl = el;
              popup.showAnchor(popup.anchorEl);
            } else {
              popup.hide();
            }
          }
        });
        editor.addListener("selectionchange", function(t, causeByUi) {
          if (!causeByUi) return;
          var html = "",
            str = "",
            img = editor.selection.getRange().getClosedNode(),
            dialogs = editor.ui._dialogs;
          if (img && img.tagName == "IMG") {
            var dialogName = "insertimageDialog";
            if (
              img.className.indexOf("edui-faked-video") != -1 ||
              img.className.indexOf("edui-upload-video") != -1
            ) {
              dialogName = "insertvideoDialog";
            }
            if (img.className.indexOf("edui-faked-webapp") != -1) {
              dialogName = "webappDialog";
            }
            if (img.src.indexOf("https://api.map.baidu.com") != -1) {
              dialogName = "mapDialog";
            }
            if (img.className.indexOf("edui-faked-music") != -1) {
              dialogName = "musicDialog";
            }
            if (
              img.src.indexOf("http://maps.google.com/maps/api/staticmap") != -1
            ) {
              dialogName = "gmapDialog";
            }
            if (img.getAttribute("anchorname")) {
              dialogName = "anchorDialog";
              html = popup.formatHtml(
                "" +
                  editor.getLang("property") +
                  ': ' +
                  editor.getLang("modify") +
                  "   " +
                  "" +
                  editor.getLang("delete") +
                  "  "
              );
            }
            if (img.getAttribute("word_img")) {
              //todo 放到dialog去做查询
              editor.word_img = [img.getAttribute("word_img")];
              dialogName = "wordimageDialog";
            }
            if (
              domUtils.hasClass(img, "loadingclass") ||
              domUtils.hasClass(img, "loaderrorclass")
            ) {
              dialogName = "";
            }
            if (!dialogs[dialogName]) {
              return;
            }
            str =
              "" +
              editor.getLang("property") +
              ": " +
              '' +
              editor.getLang("default") +
              "   " +
              '' +
              editor.getLang("justifyleft") +
              "   " +
              '' +
              editor.getLang("justifyright") +
              "   " +
              '' +
              editor.getLang("justifycenter") +
              "   " +
              "' +
              editor.getLang("modify") +
              "  ";
            !html && (html = popup.formatHtml(str));
          }
          if (editor.ui._dialogs.linkDialog) {
            var link = editor.queryCommandValue("link");
            var url;
            if (
              link &&
              (url = link.getAttribute("_href") || link.getAttribute("href", 2))
            ) {
              var txt = url;
              if (url.length > 30) {
                txt = url.substring(0, 20) + "...";
              }
              if (html) {
                html += '
';
              }
              html += popup.formatHtml(
                "" +
                  editor.getLang("anthorMsg") +
                  ': ' +
                  txt +
                  " " +
                  ' ' +
                  editor.getLang("modify") +
                  " " +
                  '  ' +
                  editor.getLang("clear") +
                  "  "
              );
              popup.showAnchor(link);
            }
          }
          if (html) {
            popup.getDom("content").innerHTML = html;
            popup.anchorEl = img || link;
            popup.showAnchor(popup.anchorEl);
          } else {
            popup.hide();
          }
        });
      }
    },
    _initToolbars: function() {
      var editor = this.editor;
      var toolbars = this.toolbars || [];
      var toolbarUis = [];
      var extraUIs = [];
      for (var i = 0; i < toolbars.length; i++) {
        var toolbar = toolbars[i];
        var toolbarUi = new baidu.editor.ui.Toolbar({
          theme: editor.options.theme
        });
        for (var j = 0; j < toolbar.length; j++) {
          var toolbarItem = toolbar[j];
          var toolbarItemUi = null;
          if (typeof toolbarItem == "string") {
            toolbarItem = toolbarItem.toLowerCase();
            if (toolbarItem == "|") {
              toolbarItem = "Separator";
            }
            if (toolbarItem == "||") {
              toolbarItem = "Breakline";
            }
            var ui = baidu.editor.ui[toolbarItem];
            if (ui) {
              if (utils.isFunction(ui)) {
                toolbarItemUi = new baidu.editor.ui[toolbarItem](editor);
              } else {
                if (ui.id && ui.id != editor.key) {
                  continue;
                }
                var itemUI = ui.execFn.call(editor, editor, toolbarItem);
                if (itemUI) {
                  if (ui.index === undefined) {
                    toolbarUi.add(itemUI);
                    continue;
                  } else {
                    extraUIs.push({
                      index: ui.index,
                      itemUI: itemUI
                    });
                  }
                }
              }
            }
            //fullscreen这里单独处理一下,放到首行去
            if (toolbarItem == "fullscreen") {
              if (toolbarUis && toolbarUis[0]) {
                toolbarUis[0].items.splice(0, 0, toolbarItemUi);
              } else {
                toolbarItemUi && toolbarUi.items.splice(0, 0, toolbarItemUi);
              }
              continue;
            }
          } else {
            toolbarItemUi = toolbarItem;
          }
          if (toolbarItemUi && toolbarItemUi.id) {
            toolbarUi.add(toolbarItemUi);
          }
        }
        toolbarUis[i] = toolbarUi;
      }
      //接受外部定制的UI
      utils.each(extraUIs, function(obj) {
        toolbarUi.add(obj.itemUI, obj.index);
      });
      this.toolbars = toolbarUis;
    },
    getHtmlTpl: function() {
      return (
        '' +
        '
" +
        '
' +
        "
" +
        //modify wdcount by matao
        '
" +
        '
' +
        "
' +
              ci +
              " "
          );
        }
        bottom.innerHTML =
          '' +
          this.editor.getLang("elementPathTip") +
          ": " +
          buff.join(" > ") +
          "
";
      } else {
        bottom.style.display = "none";
      }
    },
    disableElementPath: function() {
      var bottom = this.getDom("elementpath");
      bottom.innerHTML = "";
      bottom.style.display = "none";
      this.elementPathEnabled = false;
    },
    enableElementPath: function() {
      var bottom = this.getDom("elementpath");
      bottom.style.display = "";
      this.elementPathEnabled = true;
      this._updateElementPath();
    },
    _scale: function() {
      var doc = document,
        editor = this.editor,
        editorHolder = editor.container,
        editorDocument = editor.document,
        toolbarBox = this.getDom("toolbarbox"),
        bottombar = this.getDom("bottombar"),
        scale = this.getDom("scale"),
        scalelayer = this.getDom("scalelayer");
      var isMouseMove = false,
        position = null,
        minEditorHeight = 0,
        minEditorWidth = editor.options.minFrameWidth,
        pageX = 0,
        pageY = 0,
        scaleWidth = 0,
        scaleHeight = 0;
      function down() {
        position = domUtils.getXY(editorHolder);
        if (!minEditorHeight) {
          minEditorHeight =
            editor.options.minFrameHeight +
            toolbarBox.offsetHeight +
            bottombar.offsetHeight;
        }
        scalelayer.style.cssText =
          "position:absolute;left:0;display:;top:0;background-color:#41ABFF;opacity:0.4;filter: Alpha(opacity=40);width:" +
          editorHolder.offsetWidth +
          "px;height:" +
          editorHolder.offsetHeight +
          "px;z-index:" +
          (editor.options.zIndex + 1);
        domUtils.on(doc, "mousemove", move);
        domUtils.on(editorDocument, "mouseup", up);
        domUtils.on(doc, "mouseup", up);
      }
      var me = this;
      //by xuheng 全屏时关掉缩放
      this.editor.addListener("fullscreenchanged", function(e, fullScreen) {
        if (fullScreen) {
          me.disableScale();
        } else {
          if (me.editor.options.scaleEnabled) {
            me.enableScale();
            var tmpNode = me.editor.document.createElement("span");
            me.editor.body.appendChild(tmpNode);
            me.editor.body.style.height =
              Math.max(
                domUtils.getXY(tmpNode).y,
                me.editor.iframe.offsetHeight - 20
              ) + "px";
            domUtils.remove(tmpNode);
          }
        }
      });
      function move(event) {
        clearSelection();
        var e = event || window.event;
        pageX = e.pageX || doc.documentElement.scrollLeft + e.clientX;
        pageY = e.pageY || doc.documentElement.scrollTop + e.clientY;
        scaleWidth = pageX - position.x;
        scaleHeight = pageY - position.y;
        if (scaleWidth >= minEditorWidth) {
          isMouseMove = true;
          scalelayer.style.width = scaleWidth + "px";
        }
        if (scaleHeight >= minEditorHeight) {
          isMouseMove = true;
          scalelayer.style.height = scaleHeight + "px";
        }
      }
      function up() {
        if (isMouseMove) {
          isMouseMove = false;
          editor.ui._actualFrameWidth = scalelayer.offsetWidth - 2;
          editorHolder.style.width = editor.ui._actualFrameWidth + "px";
          editor.setHeight(
            scalelayer.offsetHeight -
              bottombar.offsetHeight -
              toolbarBox.offsetHeight -
              2,
            true
          );
        }
        if (scalelayer) {
          scalelayer.style.display = "none";
        }
        clearSelection();
        domUtils.un(doc, "mousemove", move);
        domUtils.un(editorDocument, "mouseup", up);
        domUtils.un(doc, "mouseup", up);
      }
      function clearSelection() {
        if (browser.ie) doc.selection.clear();
        else window.getSelection().removeAllRanges();
      }
      this.enableScale = function() {
        //trace:2868
        if (editor.queryCommandState("source") == 1) return;
        scale.style.display = "";
        this.scaleEnabled = true;
        domUtils.on(scale, "mousedown", down);
      };
      this.disableScale = function() {
        scale.style.display = "none";
        this.scaleEnabled = false;
        domUtils.un(scale, "mousedown", down);
      };
    },
    isFullScreen: function() {
      return this._fullscreen;
    },
    postRender: function() {
      UIBase.prototype.postRender.call(this);
      for (var i = 0; i < this.toolbars.length; i++) {
        this.toolbars[i].postRender();
      }
      var me = this;
      var timerId,
        domUtils = baidu.editor.dom.domUtils,
        updateFullScreenTime = function() {
          clearTimeout(timerId);
          timerId = setTimeout(function() {
            me._updateFullScreen();
          });
        };
      domUtils.on(window, "resize", updateFullScreenTime);
      me.addListener("destroy", function() {
        domUtils.un(window, "resize", updateFullScreenTime);
        clearTimeout(timerId);
      });
    },
    showToolbarMsg: function(msg, flag) {
      this.getDom("toolbarmsg_label").innerHTML = msg;
      this.getDom("toolbarmsg").style.display = "";
      //
      if (!flag) {
        var w = this.getDom("upload_dialog");
        w.style.display = "none";
      }
    },
    hideToolbarMsg: function() {
      this.getDom("toolbarmsg").style.display = "none";
    },
    mapUrl: function(url) {
      return url
        ? url.replace("~/", this.editor.options.UEDITOR_HOME_URL || "")
        : "";
    },
    triggerLayout: function() {
      var dom = this.getDom();
      if (dom.style.zoom == "1") {
        dom.style.zoom = "100%";
      } else {
        dom.style.zoom = "1";
      }
    }
  };
  utils.inherits(EditorUI, baidu.editor.ui.UIBase);
  var instances = {};
  UE.ui.Editor = function(options) {
    var editor = new UE.Editor(options);
    editor.options.editor = editor;
    utils.loadFile(document, {
      href:
        editor.options.themePath + editor.options.theme + "/css/neditor.css",
      tag: "link",
      type: "text/css",
      rel: "stylesheet"
    });
    var oldRender = editor.render;
    editor.render = function(holder) {
      if (holder.constructor === String) {
        editor.key = holder;
        instances[holder] = editor;
      }
      utils.domReady(function() {
        editor.langIsReady
          ? renderUI()
          : editor.addListener("langReady", renderUI);
        function renderUI() {
          editor.setOpt({
            labelMap: editor.options.labelMap || editor.getLang("labelMap")
          });
          new EditorUI(editor.options);
          if (holder) {
            if (holder.constructor === String) {
              holder = document.getElementById(holder);
            }
            holder &&
              holder.getAttribute("name") &&
              (editor.options.textarea = holder.getAttribute("name"));
            if (holder && /script|textarea/gi.test(holder.tagName)) {
              var newDiv = document.createElement("div");
              holder.parentNode.insertBefore(newDiv, holder);
              var cont = holder.value || holder.innerHTML;
              editor.options.initialContent = /^[\t\r\n ]*$/.test(cont)
                ? editor.options.initialContent
                : cont
                    .replace(/>[\n\r\t]+([ ]{4})+/g, ">")
                    .replace(/[\n\r\t]+([ ]{4})+[\n\r\t]+<");
              holder.className && (newDiv.className = holder.className);
              holder.style.cssText &&
                (newDiv.style.cssText = holder.style.cssText);
              if (/textarea/i.test(holder.tagName)) {
                editor.textarea = holder;
                editor.textarea.style.display = "none";
              } else {
                holder.parentNode.removeChild(holder);
              }
              if (holder.id) {
                newDiv.id = holder.id;
                domUtils.removeAttributes(holder, "id");
              }
              holder = newDiv;
              holder.innerHTML = "";
            }
          }
          domUtils.addClass(holder, "edui-" + editor.options.theme);
          editor.ui.render(holder);
          var opt = editor.options;
          //给实例添加一个编辑器的容器引用
          editor.container = editor.ui.getDom();
          var parents = domUtils.findParents(holder, true);
          var displays = [];
          for (var i = 0, ci; (ci = parents[i]); i++) {
            displays[i] = ci.style.display;
            ci.style.display = "block";
          }
          if (opt.initialFrameWidth) {
            opt.minFrameWidth = opt.initialFrameWidth;
          } else {
            opt.minFrameWidth = opt.initialFrameWidth = holder.offsetWidth;
            var styleWidth = holder.style.width;
            if (/%$/.test(styleWidth)) {
              opt.initialFrameWidth = styleWidth;
            }
          }
          if (opt.initialFrameHeight) {
            opt.minFrameHeight = opt.initialFrameHeight;
          } else {
            opt.initialFrameHeight = opt.minFrameHeight = holder.offsetHeight;
          }
          for (var i = 0, ci; (ci = parents[i]); i++) {
            ci.style.display = displays[i];
          }
          //编辑器最外容器设置了高度,会导致,编辑器不占位
          //todo 先去掉,没有找到原因
          if (holder.style.height) {
            holder.style.height = "";
          }
          editor.container.style.width =
            opt.initialFrameWidth +
            (/%$/.test(opt.initialFrameWidth) ? "" : "px");
          editor.container.style.zIndex = opt.zIndex;
          oldRender.call(editor, editor.ui.getDom("iframeholder"));
          editor.fireEvent("afteruiready");
        }
      });
    };
    return editor;
  };
  /**
     * @file
     * @name UE
     * @short UE
     * @desc UEditor的顶部命名空间
     */
  /**
     * @name getEditor
     * @since 1.2.4+
     * @grammar UE.getEditor(id,[opt])  =>  Editor实例
     * @desc 提供一个全局的方法得到编辑器实例
     *
     * * ''id''  放置编辑器的容器id, 如果容器下的编辑器已经存在,就直接返回
     * * ''opt'' 编辑器的可选参数
     * @example
     *  UE.getEditor('containerId',{onready:function(){//创建一个编辑器实例
     *      this.setContent('hello')
     *  }});
     *  UE.getEditor('containerId'); //返回刚创建的实例
     *
     */
  UE.getEditor = function(id, opt) {
    var editor = instances[id];
    if (!editor) {
      editor = instances[id] = new UE.ui.Editor(opt);
      editor.render(id);
    }
    return editor;
  };
  UE.delEditor = function(id) {
    var editor;
    if ((editor = instances[id])) {
      editor.key && editor.destroy();
      delete instances[id];
    }
  };
  UE.registerUI = function(uiName, fn, index, editorId) {
    utils.each(uiName.split(/\s+/), function(name) {
      baidu.editor.ui[name] = {
        id: editorId,
        execFn: fn,
        index: index
      };
    });
  };
})();
// adapter/message.js
UE.registerUI("message", function(editor) {
  var editorui = baidu.editor.ui;
  var Message = editorui.Message;
  var holder;
  var _messageItems = [];
  var me = editor;
  me.setOpt("enableMessageShow", true);
  if (me.getOpt("enableMessageShow") === false) {
    return;
  }
  me.addListener("ready", function() {
    holder = document.getElementById(me.ui.id + "_message_holder");
    updateHolderPos();
    setTimeout(function() {
      updateHolderPos();
    }, 500);
  });
  me.addListener("showmessage", function(type, opt) {
    opt = utils.isString(opt)
      ? {
          content: opt
        }
      : opt;
    var message = new Message({
      timeout: opt.timeout,
      type: opt.type,
      content: opt.content,
      keepshow: opt.keepshow,
      editor: me
    }),
      mid = opt.id || "msg_" + (+new Date()).toString(36);
    message.render(holder);
    _messageItems[mid] = message;
    message.reset(opt);
    updateHolderPos();
    return mid;
  });
  me.addListener("updatemessage", function(type, id, opt) {
    opt = utils.isString(opt)
      ? {
          content: opt
        }
      : opt;
    var message = _messageItems[id];
    message.render(holder);
    message && message.reset(opt);
  });
  me.addListener("hidemessage", function(type, id) {
    var message = _messageItems[id];
    message && message.hide();
  });
  function updateHolderPos() {
    if (!holder || !me.ui) return;
    var toolbarbox = me.ui.getDom("toolbarbox");
    if (toolbarbox) {
      holder.style.top = toolbarbox.offsetHeight + 3 + "px";
    }
    holder.style.zIndex =
      Math.max(me.options.zIndex, me.iframe.style.zIndex) + 1;
  }
});
// adapter/autosave.js
UE.registerUI("autosave", function(editor) {
  var timer = null,
    uid = null;
  editor.on("afterautosave", function() {
    clearTimeout(timer);
    timer = setTimeout(function() {
      if (uid) {
        editor.trigger("hidemessage", uid);
      }
      uid = editor.trigger("showmessage", {
        content: editor.getLang("autosave.success"),
        timeout: 2000
      });
    }, 2000);
  });
});
})();