]/.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;
+ }
+ //如果结束是文本,就有可能丢掉,所以这里手动判断一下
+ //例如 sdfsdfsdfsdfsdfsdfsdf
+ if (nextIndex < htmlstr.length) {
+ text(currentParent, htmlstr.slice(nextIndex));
+ }
+ return root;
+});
+
+
+// core/filternode.js
+/**
+ * UE过滤节点的静态方法
+ * @file
+ */
+
+/**
+ * UEditor公用空间,UEditor所有的功能都挂载在该空间下
+ * @module UE
+ */
+
+/**
+ * 根据传入节点和过滤规则过滤相应节点
+ * @module UE
+ * @since 1.2.6.1
+ * @method filterNode
+ * @param { Object } root 指定root节点
+ * @param { Object } rules 过滤规则json对象
+ * @example
+ * ```javascript
+ * UE.filterNode(root,editor.options.filterRules);
+ * ```
+ */
+var filterNode = (UE.filterNode = (function() {
+ function filterNode(node, rules) {
+ switch (node.type) {
+ case "text":
+ break;
+ case "element":
+ var val;
+ if ((val = rules[node.tagName])) {
+ if (val === "-") {
+ node.parentNode.removeChild(node);
+ } else if (utils.isFunction(val)) {
+ var parentNode = node.parentNode,
+ index = node.getIndex();
+ val(node);
+ if (node.parentNode) {
+ if (node.children) {
+ for (var i = 0, ci; (ci = node.children[i]); ) {
+ filterNode(ci, rules);
+ if (ci.parentNode) {
+ i++;
+ }
+ }
+ }
+ } else {
+ for (var i = index, ci; (ci = parentNode.children[i]); ) {
+ filterNode(ci, rules);
+ if (ci.parentNode) {
+ i++;
+ }
+ }
+ }
+ } else {
+ var attrs = val["$"];
+ if (attrs && node.attrs) {
+ var tmpAttrs = {},
+ tmpVal;
+ for (var a in attrs) {
+ tmpVal = node.getAttr(a);
+ //todo 只先对style单独处理
+ if (a == "style" && utils.isArray(attrs[a])) {
+ var tmpCssStyle = [];
+ utils.each(attrs[a], function(v) {
+ var tmp;
+ if ((tmp = node.getStyle(v))) {
+ tmpCssStyle.push(v + ":" + tmp);
+ }
+ });
+ tmpVal = tmpCssStyle.join(";");
+ }
+ if (tmpVal) {
+ tmpAttrs[a] = tmpVal;
+ }
+ }
+ node.attrs = tmpAttrs;
+ }
+ if (node.children) {
+ for (var i = 0, ci; (ci = node.children[i]); ) {
+ filterNode(ci, rules);
+ if (ci.parentNode) {
+ i++;
+ }
+ }
+ }
+ }
+ } else {
+ //如果不在名单里扣出子节点并删除该节点,cdata除外
+ if (dtd.$cdata[node.tagName]) {
+ node.parentNode.removeChild(node);
+ } else {
+ var parentNode = node.parentNode,
+ index = node.getIndex();
+ node.parentNode.removeChild(node, true);
+ for (var i = index, ci; (ci = parentNode.children[i]); ) {
+ filterNode(ci, rules);
+ if (ci.parentNode) {
+ i++;
+ }
+ }
+ }
+ }
+ break;
+ case "comment":
+ node.parentNode.removeChild(node);
+ }
+ }
+ return function(root, rules) {
+ if (utils.isEmptyObject(rules)) {
+ return root;
+ }
+ var val;
+ if ((val = rules["-"])) {
+ utils.each(val.split(" "), function(k) {
+ rules[k] = "-";
+ });
+ }
+ for (var i = 0, ci; (ci = root.children[i]); ) {
+ filterNode(ci, rules);
+ if (ci.parentNode) {
+ i++;
+ }
+ }
+ return root;
+ };
+})());
+
+
+// core/plugin.js
+/**
+ * Created with JetBrains PhpStorm.
+ * User: campaign
+ * Date: 10/8/13
+ * Time: 6:15 PM
+ * To change this template use File | Settings | File Templates.
+ */
+UE.plugin = (function() {
+ var _plugins = {};
+ return {
+ register: function(pluginName, fn, oldOptionName, afterDisabled) {
+ if (oldOptionName && utils.isFunction(oldOptionName)) {
+ afterDisabled = oldOptionName;
+ oldOptionName = null;
+ }
+ _plugins[pluginName] = {
+ optionName: oldOptionName || pluginName,
+ execFn: fn,
+ //当插件被禁用时执行
+ afterDisabled: afterDisabled
+ };
+ },
+ load: function(editor) {
+ utils.each(_plugins, function(plugin) {
+ var _export = plugin.execFn.call(editor);
+ if (editor.options[plugin.optionName] !== false) {
+ if (_export) {
+ //后边需要再做扩展
+ utils.each(_export, function(v, k) {
+ switch (k.toLowerCase()) {
+ case "shortcutkey":
+ editor.addshortcutkey(v);
+ break;
+ case "bindevents":
+ utils.each(v, function(fn, eventName) {
+ editor.addListener(eventName, fn);
+ });
+ break;
+ case "bindmultievents":
+ utils.each(utils.isArray(v) ? v : [v], function(event) {
+ var types = utils.trim(event.type).split(/\s+/);
+ utils.each(types, function(eventName) {
+ editor.addListener(eventName, event.handler);
+ });
+ });
+ break;
+ case "commands":
+ utils.each(v, function(execFn, execName) {
+ editor.commands[execName] = execFn;
+ });
+ break;
+ case "outputrule":
+ editor.addOutputRule(v);
+ break;
+ case "inputrule":
+ editor.addInputRule(v);
+ break;
+ case "defaultoptions":
+ editor.setOpt(v);
+ }
+ });
+ }
+ } else if (plugin.afterDisabled) {
+ plugin.afterDisabled.call(editor);
+ }
+ });
+ //向下兼容
+ utils.each(UE.plugins, function(plugin) {
+ plugin.call(editor);
+ });
+ },
+ run: function(pluginName, editor) {
+ var plugin = _plugins[pluginName];
+ if (plugin) {
+ plugin.exeFn.call(editor);
+ }
+ }
+ };
+})();
+
+
+// core/keymap.js
+var keymap = (UE.keymap = {
+ Backspace: 8,
+ Tab: 9,
+ Enter: 13,
+
+ Shift: 16,
+ Control: 17,
+ Alt: 18,
+ CapsLock: 20,
+
+ Esc: 27,
+
+ Spacebar: 32,
+
+ PageUp: 33,
+ PageDown: 34,
+ End: 35,
+ Home: 36,
+
+ Left: 37,
+ Up: 38,
+ Right: 39,
+ Down: 40,
+
+ Insert: 45,
+
+ Del: 46,
+
+ NumLock: 144,
+
+ Cmd: 91,
+
+ "=": 187,
+ "-": 189,
+
+ b: 66,
+ i: 73,
+ //回退
+ z: 90,
+ y: 89,
+ //粘贴
+ v: 86,
+ x: 88,
+
+ s: 83,
+
+ n: 78
+});
+
+
+// core/localstorage.js
+//存储媒介封装
+var LocalStorage = (UE.LocalStorage = (function() {
+ var storage = window.localStorage || getUserData() || null,
+ LOCAL_FILE = "localStorage";
+
+ return {
+ saveLocalData: function(key, data) {
+ if (storage && data) {
+ storage.setItem(key, data);
+ return true;
+ }
+
+ return false;
+ },
+
+ getLocalData: function(key) {
+ if (storage) {
+ return storage.getItem(key);
+ }
+
+ return null;
+ },
+
+ removeItem: function(key) {
+ storage && storage.removeItem(key);
+ }
+ };
+
+ function getUserData() {
+ var container = document.createElement("div");
+ container.style.display = "none";
+
+ if (!container.addBehavior) {
+ return null;
+ }
+
+ container.addBehavior("#default#userdata");
+
+ return {
+ getItem: function(key) {
+ var result = null;
+
+ try {
+ document.body.appendChild(container);
+ container.load(LOCAL_FILE);
+ result = container.getAttribute(key);
+ document.body.removeChild(container);
+ } catch (e) {}
+
+ return result;
+ },
+
+ setItem: function(key, value) {
+ document.body.appendChild(container);
+ container.setAttribute(key, value);
+ container.save(LOCAL_FILE);
+ document.body.removeChild(container);
+ },
+
+ //// 暂时没有用到
+ //clear: function () {
+ //
+ // var expiresTime = new Date();
+ // expiresTime.setFullYear(expiresTime.getFullYear() - 1);
+ // document.body.appendChild(container);
+ // container.expires = expiresTime.toUTCString();
+ // container.save(LOCAL_FILE);
+ // document.body.removeChild(container);
+ //
+ //},
+
+ removeItem: function(key) {
+ document.body.appendChild(container);
+ container.removeAttribute(key);
+ container.save(LOCAL_FILE);
+ document.body.removeChild(container);
+ }
+ };
+ }
+})());
+
+;(function() {
+ var ROOTKEY = "ueditor_preference";
+
+ UE.Editor.prototype.setPreferences = function(key, value) {
+ var obj = {};
+ if (utils.isString(key)) {
+ obj[key] = value;
+ } else {
+ obj = key;
+ }
+ var data = LocalStorage.getLocalData(ROOTKEY);
+ if (data && (data = utils.str2json(data))) {
+ utils.extend(data, obj);
+ } else {
+ data = obj;
+ }
+ data && LocalStorage.saveLocalData(ROOTKEY, utils.json2str(data));
+ };
+
+ UE.Editor.prototype.getPreferences = function(key) {
+ var data = LocalStorage.getLocalData(ROOTKEY);
+ if (data && (data = utils.str2json(data))) {
+ return key ? data[key] : data;
+ }
+ return null;
+ };
+
+ UE.Editor.prototype.removePreferences = function(key) {
+ var data = LocalStorage.getLocalData(ROOTKEY);
+ if (data && (data = utils.str2json(data))) {
+ data[key] = undefined;
+ delete data[key];
+ }
+ data && LocalStorage.saveLocalData(ROOTKEY, utils.json2str(data));
+ };
+})();
+
+
+// plugins/defaultfilter.js
+///import core
+///plugin 编辑器默认的过滤转换机制
+
+UE.plugins["defaultfilter"] = function() {
+ var me = this;
+ me.setOpt({
+ allowDivTransToP: true,
+ disabledTableInTable: true,
+ 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 ? " " : " ");
+ }
+ break;
+ case "div":
+ if (node.getAttr("cdata_tag")) {
+ break;
+ }
+ //针对代码这里不处理插入代码的div
+ val = node.getAttr("class");
+ if (val && /^line number\d+/.test(val)) {
+ break;
+ }
+ if (!allowDivTransToP) {
+ break;
+ }
+ var tmpNode,
+ p = UE.uNode.createElement("p");
+ while ((tmpNode = node.firstChild())) {
+ if (
+ tmpNode.type == "text" ||
+ !UE.dom.dtd.$block[tmpNode.tagName]
+ ) {
+ p.appendChild(tmpNode);
+ } else {
+ if (p.firstChild()) {
+ node.parentNode.insertBefore(p, node);
+ p = UE.uNode.createElement("p");
+ } else {
+ node.parentNode.insertBefore(tmpNode, node);
+ }
+ }
+ }
+ if (p.firstChild()) {
+ node.parentNode.insertBefore(p, node);
+ }
+ node.parentNode.removeChild(node);
+ break;
+ case "dl":
+ node.tagName = "ul";
+ break;
+ case "dt":
+ case "dd":
+ node.tagName = "li";
+ break;
+ case "li":
+ var className = node.getAttr("class");
+ if (!className || !/list\-/.test(className)) {
+ node.setAttr();
+ }
+ var tmpNodes = node.getNodesByTagName("ol ul");
+ UE.utils.each(tmpNodes, function(n) {
+ node.parentNode.insertAfter(n, node);
+ });
+ break;
+ case "td":
+ case "th":
+ case "caption":
+ if (!node.children || !node.children.length) {
+ node.appendChild(
+ browser.ie11below
+ ? UE.uNode.createText(" ")
+ : UE.uNode.createElement("br")
+ );
+ }
+ break;
+ case "table":
+ if (me.options.disabledTableInTable && tdParent(node)) {
+ node.parentNode.insertBefore(
+ UE.uNode.createText(node.innerText()),
+ node
+ );
+ node.parentNode.removeChild(node);
+ }
+ }
+ }
+ // if(node.type == 'comment'){
+ // node.parentNode.removeChild(node);
+ // }
+ });
+ });
+
+ //从编辑器出去的内容处理
+ me.addOutputRule(function(root) {
+ var val;
+ root.traversal(function(node) {
+ if (node.type == "element") {
+ if (
+ me.options.autoClearEmptyNode &&
+ dtd.$inline[node.tagName] &&
+ !dtd.$empty[node.tagName] &&
+ (!node.attrs || utils.isEmptyObject(node.attrs))
+ ) {
+ if (!node.firstChild()) node.parentNode.removeChild(node);
+ else if (
+ node.tagName == "span" &&
+ (!node.attrs || utils.isEmptyObject(node.attrs))
+ ) {
+ node.parentNode.removeChild(node, true);
+ }
+ return;
+ }
+ switch (node.tagName) {
+ case "div":
+ if ((val = node.getAttr("cdata_tag"))) {
+ node.tagName = val;
+ node.appendChild(UE.uNode.createText(node.getAttr("cdata_data")));
+ node.setAttr({
+ cdata_tag: "",
+ cdata_data: "",
+ _ue_custom_node_: ""
+ });
+ }
+ break;
+ case "a":
+ if ((val = node.getAttr("_href"))) {
+ node.setAttr({
+ href: utils.html(val),
+ _href: ""
+ });
+ }
+ break;
+ break;
+ case "span":
+ val = node.getAttr("id");
+ if (val && /^_baidu_bookmark_/i.test(val)) {
+ node.parentNode.removeChild(node);
+ }
+ //将color的rgb格式转换为#16进制格式
+ if (me.getOpt("rgb2Hex")) {
+ var cssStyle = node.getAttr("style");
+ if (cssStyle) {
+ node.setAttr(
+ "style",
+ cssStyle.replace(/rgba?\(([\d,\s]+)\)/g, function(a, value) {
+ var array = value.split(",");
+ if (array.length > 3) return "";
+ value = "#";
+ for (var i = 0, color; (color = array[i++]); ) {
+ color = parseInt(
+ color.replace(/[^\d]/gi, ""),
+ 10
+ ).toString(16);
+ value += color.length == 1 ? "0" + color : color;
+ }
+ return value.toUpperCase();
+ })
+ );
+ }
+ }
+ break;
+ case "img":
+ if ((val = node.getAttr("_src"))) {
+ node.setAttr({
+ src: node.getAttr("_src"),
+ _src: ""
+ });
+ }
+ }
+ }
+ });
+ });
+};
+
+
+// plugins/inserthtml.js
+/**
+ * 插入html字符串插件
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 插入html代码
+ * @command inserthtml
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @param { String } html 插入的html字符串
+ * @remaind 插入的标签内容是在当前的选区位置上插入,如果当前是闭合状态,那直接插入内容, 如果当前是选中状态,将先清除当前选中内容后,再做插入
+ * @warning 注意:该命令会对当前选区的位置,对插入的内容进行过滤转换处理。 过滤的规则遵循html语意化的原则。
+ * @example
+ * ```javascript
+ * //xxx[BB]xxx 当前选区为非闭合选区,选中BB这两个文本
+ * //执行命令,插入CC
+ * //插入后的效果 xxxCCxxx
+ * //xx|xxx 当前选区为闭合状态
+ * //插入CC
+ * //结果 xx CC xxx
+ * //xxxx |xxx 当前选区在两个p标签之间
+ * //插入 xxxx
+ * //结果 xxxx xxxx xxx
+ * ```
+ */
+
+UE.commands["inserthtml"] = {
+ execCommand: function(command, html, notNeedFilter) {
+ var me = this,
+ range,
+ div;
+ if (!html) {
+ return;
+ }
+ if (me.fireEvent("beforeinserthtml", html) === true) {
+ return;
+ }
+ range = me.selection.getRange();
+ div = range.document.createElement("div");
+ div.style.display = "inline";
+
+ if (!notNeedFilter) {
+ var root = UE.htmlparser(html);
+ //如果给了过滤规则就先进行过滤
+ if (me.options.filterRules) {
+ UE.filterNode(root, me.options.filterRules);
+ }
+ //执行默认的处理
+ me.filterInputRule(root);
+ html = root.toHtml();
+ }
+ div.innerHTML = utils.trim(html);
+
+ if (!range.collapsed) {
+ var tmpNode = range.startContainer;
+ if (domUtils.isFillChar(tmpNode)) {
+ range.setStartBefore(tmpNode);
+ }
+ tmpNode = range.endContainer;
+ if (domUtils.isFillChar(tmpNode)) {
+ range.setEndAfter(tmpNode);
+ }
+ range.txtToElmBoundary();
+ //结束边界可能放到了br的前边,要把br包含进来
+ // x[xxx]
+ if (range.endContainer && range.endContainer.nodeType == 1) {
+ tmpNode = range.endContainer.childNodes[range.endOffset];
+ if (tmpNode && domUtils.isBr(tmpNode)) {
+ range.setEndAfter(tmpNode);
+ }
+ }
+ if (range.startOffset == 0) {
+ tmpNode = range.startContainer;
+ if (domUtils.isBoundaryNode(tmpNode, "firstChild")) {
+ tmpNode = range.endContainer;
+ if (
+ range.endOffset ==
+ (tmpNode.nodeType == 3
+ ? tmpNode.nodeValue.length
+ : tmpNode.childNodes.length) &&
+ domUtils.isBoundaryNode(tmpNode, "lastChild")
+ ) {
+ me.body.innerHTML = "" + (browser.ie ? "" : " ") + " ";
+ range.setStart(me.body.firstChild, 0).collapse(true);
+ }
+ }
+ }
+ !range.collapsed && range.deleteContents();
+ if (range.startContainer.nodeType == 1) {
+ var child = range.startContainer.childNodes[range.startOffset],
+ pre;
+ if (
+ child &&
+ domUtils.isBlockElm(child) &&
+ (pre = child.previousSibling) &&
+ domUtils.isBlockElm(pre)
+ ) {
+ range.setEnd(pre, pre.childNodes.length).collapse();
+ while (child.firstChild) {
+ pre.appendChild(child.firstChild);
+ }
+ domUtils.remove(child);
+ }
+ }
+ }
+
+ var child,
+ parent,
+ pre,
+ tmp,
+ hadBreak = 0,
+ nextNode;
+ //如果当前位置选中了fillchar要干掉,要不会产生空行
+ if (range.inFillChar()) {
+ child = range.startContainer;
+ if (domUtils.isFillChar(child)) {
+ range.setStartBefore(child).collapse(true);
+ domUtils.remove(child);
+ } else if (domUtils.isFillChar(child, true)) {
+ child.nodeValue = child.nodeValue.replace(fillCharReg, "");
+ range.startOffset--;
+ range.collapsed && range.collapse(true);
+ }
+ }
+ //列表单独处理
+ var li = domUtils.findParentByTagName(range.startContainer, "li", true);
+ if (li) {
+ var next, last;
+ while ((child = div.firstChild)) {
+ //针对hr单独处理一下先
+ while (
+ child &&
+ (child.nodeType == 3 ||
+ !domUtils.isBlockElm(child) ||
+ child.tagName == "HR")
+ ) {
+ next = child.nextSibling;
+ range.insertNode(child).collapse();
+ last = child;
+ child = next;
+ }
+ if (child) {
+ if (/^(ol|ul)$/i.test(child.tagName)) {
+ while (child.firstChild) {
+ last = child.firstChild;
+ domUtils.insertAfter(li, child.firstChild);
+ li = li.nextSibling;
+ }
+ domUtils.remove(child);
+ } else {
+ var tmpLi;
+ next = child.nextSibling;
+ tmpLi = me.document.createElement("li");
+ domUtils.insertAfter(li, tmpLi);
+ tmpLi.appendChild(child);
+ last = child;
+ child = next;
+ li = tmpLi;
+ }
+ }
+ }
+ li = domUtils.findParentByTagName(range.startContainer, "li", true);
+ if (domUtils.isEmptyBlock(li)) {
+ domUtils.remove(li);
+ }
+ if (last) {
+ range.setStartAfter(last).collapse(true).select(true);
+ }
+ } else {
+ while ((child = div.firstChild)) {
+ if (hadBreak) {
+ var p = me.document.createElement("p");
+ while (child && (child.nodeType == 3 || !dtd.$block[child.tagName])) {
+ nextNode = child.nextSibling;
+ p.appendChild(child);
+ child = nextNode;
+ }
+ if (p.firstChild) {
+ child = p;
+ }
+ }
+ range.insertNode(child);
+ nextNode = child.nextSibling;
+ if (
+ !hadBreak &&
+ child.nodeType == domUtils.NODE_ELEMENT &&
+ domUtils.isBlockElm(child)
+ ) {
+ parent = domUtils.findParent(child, function(node) {
+ return domUtils.isBlockElm(node);
+ });
+ if (
+ parent &&
+ parent.tagName.toLowerCase() != "body" &&
+ !(
+ dtd[parent.tagName][child.nodeName] && child.parentNode === parent
+ )
+ ) {
+ if (!dtd[parent.tagName][child.nodeName]) {
+ pre = parent;
+ } else {
+ tmp = child.parentNode;
+ while (tmp !== parent) {
+ pre = tmp;
+ tmp = tmp.parentNode;
+ }
+ }
+
+ domUtils.breakParent(child, pre || tmp);
+ //去掉break后前一个多余的节点 |<[p> ==> |
+ var pre = child.previousSibling;
+ domUtils.trimWhiteTextNode(pre);
+ if (!pre.childNodes.length) {
+ domUtils.remove(pre);
+ }
+ //trace:2012,在非ie的情况,切开后剩下的节点有可能不能点入光标添加br占位
+
+ if (
+ !browser.ie &&
+ (next = child.nextSibling) &&
+ domUtils.isBlockElm(next) &&
+ next.lastChild &&
+ !domUtils.isBr(next.lastChild)
+ ) {
+ next.appendChild(me.document.createElement("br"));
+ }
+ hadBreak = 1;
+ }
+ }
+ var next = child.nextSibling;
+ if (!div.firstChild && next && domUtils.isBlockElm(next)) {
+ range.setStart(next, 0).collapse(true);
+ break;
+ }
+ range.setEndAfter(child).collapse();
+ }
+
+ child = range.startContainer;
+
+ if (nextNode && domUtils.isBr(nextNode)) {
+ domUtils.remove(nextNode);
+ }
+ //用chrome可能有空白展位符
+ if (domUtils.isBlockElm(child) && domUtils.isEmptyNode(child)) {
+ if ((nextNode = child.nextSibling)) {
+ domUtils.remove(child);
+ if (nextNode.nodeType == 1 && dtd.$block[nextNode.tagName]) {
+ range.setStart(nextNode, 0).collapse(true).shrinkBoundary();
+ }
+ } else {
+ try {
+ child.innerHTML = browser.ie ? domUtils.fillChar : " ";
+ } catch (e) {
+ range.setStartBefore(child);
+ domUtils.remove(child);
+ }
+ }
+ }
+ //加上true因为在删除表情等时会删两次,第一次是删的fillData
+ try {
+ range.select(true);
+ } catch (e) {}
+ }
+
+ setTimeout(function() {
+ range = me.selection.getRange();
+ range.scrollToView(
+ me.autoHeightEnabled,
+ me.autoHeightEnabled ? domUtils.getXY(me.iframe).y : 0
+ );
+ me.fireEvent("afterinserthtml", html);
+ }, 200);
+ }
+};
+
+
+// plugins/autotypeset.js
+/**
+ * 自动排版
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 对当前编辑器的内容执行自动排版, 排版的行为根据config配置文件里的“autotypeset”选项进行控制。
+ * @command autotypeset
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'autotypeset' );
+ * ```
+ */
+
+UE.plugins["autotypeset"] = function() {
+ this.setOpt({
+ autotypeset: {
+ mergeEmptyline: true, //合并空行
+ removeClass: true, //去掉冗余的class
+ removeEmptyline: false, //去掉空行
+ textAlign: "left", //段落的排版方式,可以是 left,right,center,justify 去掉这个属性表示不执行排版
+ imageBlockLine: "center", //图片的浮动方式,独占一行剧中,左右浮动,默认: center,left,right,none 去掉这个属性表示不执行排版
+ pasteFilter: false, //根据规则过滤没事粘贴进来的内容
+ clearFontSize: false, //去掉所有的内嵌字号,使用编辑器默认的字号
+ clearFontFamily: false, //去掉所有的内嵌字体,使用编辑器默认的字体
+ removeEmptyNode: false, // 去掉空节点
+ //可以去掉的标签
+ removeTagNames: utils.extend({ div: 1 }, dtd.$removeEmpty),
+ indent: false, // 行首缩进
+ indentValue: "2em", //行首缩进的大小
+ bdc2sb: false,
+ tobdc: false
+ }
+ });
+
+ var me = this,
+ opt = me.options.autotypeset,
+ remainClass = {
+ selectTdClass: 1,
+ pagebreak: 1,
+ anchorclass: 1
+ },
+ remainTag = {
+ li: 1
+ },
+ tags = {
+ div: 1,
+ p: 1,
+ //trace:2183 这些也认为是行
+ blockquote: 1,
+ center: 1,
+ h1: 1,
+ h2: 1,
+ h3: 1,
+ h4: 1,
+ h5: 1,
+ h6: 1,
+ span: 1
+ },
+ highlightCont;
+ //升级了版本,但配置项目里没有autotypeset
+ if (!opt) {
+ return;
+ }
+
+ readLocalOpts();
+
+ function isLine(node, notEmpty) {
+ if (!node || node.nodeType == 3) return 0;
+ if (domUtils.isBr(node)) return 1;
+ if (node && node.parentNode && tags[node.tagName.toLowerCase()]) {
+ if (
+ (highlightCont && highlightCont.contains(node)) ||
+ node.getAttribute("pagebreak")
+ ) {
+ return 0;
+ }
+
+ return notEmpty
+ ? !domUtils.isEmptyBlock(node)
+ : domUtils.isEmptyBlock(
+ node,
+ new RegExp("[\\s" + domUtils.fillChar + "]", "g")
+ );
+ }
+ }
+
+ function removeNotAttributeSpan(node) {
+ if (!node.style.cssText) {
+ domUtils.removeAttributes(node, ["style"]);
+ if (
+ node.tagName.toLowerCase() == "span" &&
+ domUtils.hasNoAttributes(node)
+ ) {
+ domUtils.remove(node, true);
+ }
+ }
+ }
+ function autotype(type, html) {
+ var me = this,
+ cont;
+ if (html) {
+ if (!opt.pasteFilter) {
+ return;
+ }
+ cont = me.document.createElement("div");
+ cont.innerHTML = html.html;
+ } else {
+ cont = me.document.body;
+ }
+ var nodes = domUtils.getElementsByTagName(cont, "*");
+
+ // 行首缩进,段落方向,段间距,段内间距
+ for (var i = 0, ci; (ci = nodes[i++]); ) {
+ if (me.fireEvent("excludeNodeinautotype", ci) === true) {
+ continue;
+ }
+ //font-size
+ if (opt.clearFontSize && ci.style.fontSize) {
+ domUtils.removeStyle(ci, "font-size");
+
+ removeNotAttributeSpan(ci);
+ }
+ //font-family
+ if (opt.clearFontFamily && ci.style.fontFamily) {
+ domUtils.removeStyle(ci, "font-family");
+ removeNotAttributeSpan(ci);
+ }
+
+ if (isLine(ci)) {
+ //合并空行
+ if (opt.mergeEmptyline) {
+ var next = ci.nextSibling,
+ tmpNode,
+ isBr = domUtils.isBr(ci);
+ while (isLine(next)) {
+ tmpNode = next;
+ next = tmpNode.nextSibling;
+ if (isBr && (!next || (next && !domUtils.isBr(next)))) {
+ break;
+ }
+ domUtils.remove(tmpNode);
+ }
+ }
+ //去掉空行,保留占位的空行
+ if (
+ opt.removeEmptyline &&
+ domUtils.inDoc(ci, cont) &&
+ !remainTag[ci.parentNode.tagName.toLowerCase()]
+ ) {
+ if (domUtils.isBr(ci)) {
+ next = ci.nextSibling;
+ if (next && !domUtils.isBr(next)) {
+ continue;
+ }
+ }
+ domUtils.remove(ci);
+ continue;
+ }
+ }
+ if (isLine(ci, true) && ci.tagName != "SPAN") {
+ if (opt.indent) {
+ ci.style.textIndent = opt.indentValue;
+ }
+ if (opt.textAlign) {
+ ci.style.textAlign = opt.textAlign;
+ }
+ // if(opt.lineHeight)
+ // ci.style.lineHeight = opt.lineHeight + 'cm';
+ }
+
+ //去掉class,保留的class不去掉
+ if (
+ opt.removeClass &&
+ ci.className &&
+ !remainClass[ci.className.toLowerCase()]
+ ) {
+ if (highlightCont && highlightCont.contains(ci)) {
+ continue;
+ }
+ domUtils.removeAttributes(ci, ["class"]);
+ }
+
+ //表情不处理
+ if (
+ opt.imageBlockLine &&
+ ci.tagName.toLowerCase() == "img" &&
+ !ci.getAttribute("emotion")
+ ) {
+ if (html) {
+ var img = ci;
+ switch (opt.imageBlockLine) {
+ case "left":
+ case "right":
+ case "none":
+ var pN = img.parentNode,
+ tmpNode,
+ pre,
+ next;
+ while (dtd.$inline[pN.tagName] || pN.tagName == "A") {
+ pN = pN.parentNode;
+ }
+ tmpNode = pN;
+ if (
+ tmpNode.tagName == "P" &&
+ domUtils.getStyle(tmpNode, "text-align") == "center"
+ ) {
+ if (
+ !domUtils.isBody(tmpNode) &&
+ domUtils.getChildCount(tmpNode, function(node) {
+ return !domUtils.isBr(node) && !domUtils.isWhitespace(node);
+ }) == 1
+ ) {
+ pre = tmpNode.previousSibling;
+ next = tmpNode.nextSibling;
+ if (
+ pre &&
+ next &&
+ pre.nodeType == 1 &&
+ next.nodeType == 1 &&
+ pre.tagName == next.tagName &&
+ domUtils.isBlockElm(pre)
+ ) {
+ pre.appendChild(tmpNode.firstChild);
+ while (next.firstChild) {
+ pre.appendChild(next.firstChild);
+ }
+ domUtils.remove(tmpNode);
+ domUtils.remove(next);
+ } else {
+ domUtils.setStyle(tmpNode, "text-align", "");
+ }
+ }
+ }
+ domUtils.setStyle(img, "float", opt.imageBlockLine);
+ break;
+ case "center":
+ if (me.queryCommandValue("imagefloat") != "center") {
+ pN = img.parentNode;
+ domUtils.setStyle(img, "float", "none");
+ tmpNode = img;
+ while (
+ pN &&
+ domUtils.getChildCount(pN, function(node) {
+ return !domUtils.isBr(node) && !domUtils.isWhitespace(node);
+ }) == 1 &&
+ (dtd.$inline[pN.tagName] || pN.tagName == "A")
+ ) {
+ tmpNode = pN;
+ pN = pN.parentNode;
+ }
+ var pNode = me.document.createElement("p");
+ domUtils.setAttributes(pNode, {
+ style: "text-align:center"
+ });
+ tmpNode.parentNode.insertBefore(pNode, tmpNode);
+ pNode.appendChild(tmpNode);
+ domUtils.setStyle(tmpNode, "float", "");
+ }
+ }
+ } else {
+ var range = me.selection.getRange();
+ range.selectNode(ci).select();
+ me.execCommand("imagefloat", opt.imageBlockLine);
+ }
+ }
+
+ //去掉冗余的标签
+ if (opt.removeEmptyNode) {
+ if (
+ opt.removeTagNames[ci.tagName.toLowerCase()] &&
+ domUtils.hasNoAttributes(ci) &&
+ domUtils.isEmptyBlock(ci)
+ ) {
+ domUtils.remove(ci);
+ }
+ }
+ }
+ if (opt.tobdc) {
+ var root = UE.htmlparser(cont.innerHTML);
+ root.traversal(function(node) {
+ if (node.type == "text") {
+ node.data = ToDBC(node.data);
+ }
+ });
+ cont.innerHTML = root.toHtml();
+ }
+ if (opt.bdc2sb) {
+ var root = UE.htmlparser(cont.innerHTML);
+ root.traversal(function(node) {
+ if (node.type == "text") {
+ node.data = DBC2SB(node.data);
+ }
+ });
+ cont.innerHTML = root.toHtml();
+ }
+ if (html) {
+ html.html = cont.innerHTML;
+ }
+ }
+ if (opt.pasteFilter) {
+ me.addListener("beforepaste", autotype);
+ }
+
+ function DBC2SB(str) {
+ var result = "";
+ for (var i = 0; i < str.length; i++) {
+ var code = str.charCodeAt(i); //获取当前字符的unicode编码
+ if (code >= 65281 && code <= 65373) {
+ //在这个unicode编码范围中的是所有的英文字母已经各种字符
+ result += String.fromCharCode(str.charCodeAt(i) - 65248); //把全角字符的unicode编码转换为对应半角字符的unicode码
+ } else if (code == 12288) {
+ //空格
+ result += String.fromCharCode(str.charCodeAt(i) - 12288 + 32);
+ } else {
+ result += str.charAt(i);
+ }
+ }
+ return result;
+ }
+ function ToDBC(txtstring) {
+ txtstring = utils.html(txtstring);
+ var tmp = "";
+ var mark = ""; /*用于判断,如果是html尖括里的标记,则不进行全角的转换*/
+ for (var i = 0; i < txtstring.length; i++) {
+ if (txtstring.charCodeAt(i) == 32) {
+ tmp = tmp + String.fromCharCode(12288);
+ } else if (txtstring.charCodeAt(i) < 127) {
+ tmp = tmp + String.fromCharCode(txtstring.charCodeAt(i) + 65248);
+ } else {
+ tmp += txtstring.charAt(i);
+ }
+ }
+ return tmp;
+ }
+
+ function readLocalOpts() {
+ var cookieOpt = me.getPreferences("autotypeset");
+ utils.extend(me.options.autotypeset, cookieOpt);
+ }
+
+ me.commands["autotypeset"] = {
+ execCommand: function() {
+ me.removeListener("beforepaste", autotype);
+ if (opt.pasteFilter) {
+ me.addListener("beforepaste", autotype);
+ }
+ autotype.call(me);
+ }
+ };
+};
+
+
+// plugins/autosubmit.js
+/**
+ * 快捷键提交
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 提交表单
+ * @command autosubmit
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'autosubmit' );
+ * ```
+ */
+
+UE.plugin.register("autosubmit", function() {
+ return {
+ shortcutkey: {
+ autosubmit: "ctrl+13" //手动提交
+ },
+ commands: {
+ autosubmit: {
+ execCommand: function() {
+ var me = this,
+ form = domUtils.findParentByTagName(me.iframe, "form", false);
+ if (form) {
+ if (me.fireEvent("beforesubmit") === false) {
+ return;
+ }
+ me.sync();
+ form.submit();
+ }
+ }
+ }
+ }
+ };
+});
+
+
+// plugins/background.js
+/**
+ * 背景插件,为UEditor提供设置背景功能
+ * @file
+ * @since 1.2.6.1
+ */
+UE.plugin.register("background", function() {
+ var me = this,
+ cssRuleId = "editor_background",
+ isSetColored,
+ reg = new RegExp("body[\\s]*\\{(.+)\\}", "i");
+
+ function stringToObj(str) {
+ var obj = {},
+ styles = str.split(";");
+ utils.each(styles, function(v) {
+ var index = v.indexOf(":"),
+ key = utils.trim(v.substr(0, index)).toLowerCase();
+ key && (obj[key] = utils.trim(v.substr(index + 1) || ""));
+ });
+ return obj;
+ }
+
+ function setBackground(obj) {
+ if (obj) {
+ var styles = [];
+ for (var name in obj) {
+ if (obj.hasOwnProperty(name)) {
+ styles.push(name + ":" + obj[name] + "; ");
+ }
+ }
+ utils.cssRule(
+ cssRuleId,
+ styles.length ? "body{" + styles.join("") + "}" : "",
+ me.document
+ );
+ } else {
+ utils.cssRule(cssRuleId, "", me.document);
+ }
+ }
+ //重写editor.hasContent方法
+
+ var orgFn = me.hasContents;
+ me.hasContents = function() {
+ if (me.queryCommandValue("background")) {
+ return true;
+ }
+ return orgFn.apply(me, arguments);
+ };
+ return {
+ bindEvents: {
+ getAllHtml: function(type, headHtml) {
+ var body = this.body,
+ su = domUtils.getComputedStyle(body, "background-image"),
+ url = "";
+ if (su.indexOf(me.options.imagePath) > 0) {
+ url = su
+ .substring(su.indexOf(me.options.imagePath), su.length - 1)
+ .replace(/"|\(|\)/gi, "");
+ } else {
+ url = su != "none" ? su.replace(/url\("?|"?\)/gi, "") : "";
+ }
+ var html = ' ";
+ headHtml.push(html);
+ },
+ aftersetcontent: function() {
+ if (isSetColored == false) setBackground();
+ }
+ },
+ inputRule: function(root) {
+ isSetColored = false;
+ utils.each(root.getNodesByTagName("p"), function(p) {
+ var styles = p.getAttr("data-background");
+ if (styles) {
+ isSetColored = true;
+ setBackground(stringToObj(styles));
+ p.parentNode.removeChild(p);
+ }
+ });
+ },
+ outputRule: function(root) {
+ var me = this,
+ styles = (utils.cssRule(cssRuleId, me.document) || "")
+ .replace(/[\n\r]+/g, "")
+ .match(reg);
+ if (styles) {
+ root.appendChild(
+ UE.uNode.createElement(
+ '
'
+ )
+ );
+ }
+ },
+ commands: {
+ background: {
+ execCommand: function(cmd, obj) {
+ setBackground(obj);
+ },
+ queryCommandValue: function() {
+ var me = this,
+ styles = (utils.cssRule(cssRuleId, me.document) || "")
+ .replace(/[\n\r]+/g, "")
+ .match(reg);
+ return styles ? stringToObj(styles[1]) : null;
+ },
+ notNeedUndo: true
+ }
+ }
+ };
+});
+
+
+// plugins/image.js
+/**
+ * 图片插入、排版插件
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 图片对齐方式
+ * @command imagefloat
+ * @method execCommand
+ * @remind 值center为独占一行居中
+ * @param { String } cmd 命令字符串
+ * @param { String } align 对齐方式,可传left、right、none、center
+ * @remaind center表示图片独占一行
+ * @example
+ * ```javascript
+ * editor.execCommand( 'imagefloat', 'center' );
+ * ```
+ */
+
+/**
+ * 如果选区所在位置是图片区域
+ * @command imagefloat
+ * @method queryCommandValue
+ * @param { String } cmd 命令字符串
+ * @return { String } 返回图片对齐方式
+ * @example
+ * ```javascript
+ * editor.queryCommandValue( 'imagefloat' );
+ * ```
+ */
+
+UE.commands["imagefloat"] = {
+ execCommand: function(cmd, align) {
+ var me = this,
+ range = me.selection.getRange();
+ if (!range.collapsed) {
+ var img = range.getClosedNode();
+ if (img && img.tagName == "IMG") {
+ switch (align) {
+ case "left":
+ case "right":
+ case "none":
+ var pN = img.parentNode,
+ tmpNode,
+ pre,
+ next;
+ while (dtd.$inline[pN.tagName] || pN.tagName == "A") {
+ pN = pN.parentNode;
+ }
+ tmpNode = pN;
+ if (
+ tmpNode.tagName == "P" &&
+ domUtils.getStyle(tmpNode, "text-align") == "center"
+ ) {
+ if (
+ !domUtils.isBody(tmpNode) &&
+ domUtils.getChildCount(tmpNode, function(node) {
+ return !domUtils.isBr(node) && !domUtils.isWhitespace(node);
+ }) == 1
+ ) {
+ pre = tmpNode.previousSibling;
+ next = tmpNode.nextSibling;
+ if (
+ pre &&
+ next &&
+ pre.nodeType == 1 &&
+ next.nodeType == 1 &&
+ pre.tagName == next.tagName &&
+ domUtils.isBlockElm(pre)
+ ) {
+ pre.appendChild(tmpNode.firstChild);
+ while (next.firstChild) {
+ pre.appendChild(next.firstChild);
+ }
+ domUtils.remove(tmpNode);
+ domUtils.remove(next);
+ } else {
+ domUtils.setStyle(tmpNode, "text-align", "");
+ }
+ }
+
+ range.selectNode(img).select();
+ }
+ domUtils.setStyle(img, "float", align == "none" ? "" : align);
+ if (align == "none") {
+ domUtils.removeAttributes(img, "align");
+ }
+
+ break;
+ case "center":
+ if (me.queryCommandValue("imagefloat") != "center") {
+ 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 =
+ ' ";
+ if (ci["floatStyle"] == "center") {
+ str = '' + str + " ";
+ }
+ html.push(str);
+ } else {
+ for (var i = 0; (ci = opt[i++]); ) {
+ str =
+ " ";
+ html.push(str);
+ }
+ }
+
+ me.execCommand("insertHtml", html.join(""));
+ }
+
+ me.fireEvent("afterinsertimage", opt);
+ }
+};
+
+
+// plugins/justify.js
+/**
+ * 段落格式
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 段落对齐方式
+ * @command justify
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @param { String } align 对齐方式:left => 居左,right => 居右,center => 居中,justify => 两端对齐
+ * @example
+ * ```javascript
+ * editor.execCommand( 'justify', 'center' );
+ * ```
+ */
+/**
+ * 如果选区所在位置是段落区域,返回当前段落对齐方式
+ * @command justify
+ * @method queryCommandValue
+ * @param { String } cmd 命令字符串
+ * @return { String } 返回段落对齐方式
+ * @example
+ * ```javascript
+ * editor.queryCommandValue( 'justify' );
+ * ```
+ */
+
+UE.plugins["justify"] = function() {
+ var me = this,
+ block = domUtils.isBlockElm,
+ defaultValue = {
+ left: 1,
+ right: 1,
+ center: 1,
+ justify: 1
+ },
+ doJustify = function(range, style) {
+ var bookmark = range.createBookmark(),
+ filterFn = function(node) {
+ return node.nodeType == 1
+ ? node.tagName.toLowerCase() != "br" &&
+ !domUtils.isBookmarkNode(node)
+ : !domUtils.isWhitespace(node);
+ };
+
+ range.enlarge(true);
+ var bookmark2 = range.createBookmark(),
+ current = domUtils.getNextDomNode(bookmark2.start, false, filterFn),
+ tmpRange = range.cloneRange(),
+ tmpNode;
+ while (
+ current &&
+ !(
+ domUtils.getPosition(current, bookmark2.end) &
+ domUtils.POSITION_FOLLOWING
+ )
+ ) {
+ if (current.nodeType == 3 || !block(current)) {
+ tmpRange.setStartBefore(current);
+ while (current && current !== bookmark2.end && !block(current)) {
+ tmpNode = current;
+ current = domUtils.getNextDomNode(current, false, null, function(
+ node
+ ) {
+ return !block(node);
+ });
+ }
+ tmpRange.setEndAfter(tmpNode);
+ var common = tmpRange.getCommonAncestor();
+ if (!domUtils.isBody(common) && block(common)) {
+ domUtils.setStyles(
+ common,
+ utils.isString(style) ? { "text-align": style } : style
+ );
+ current = common;
+ } else {
+ var p = range.document.createElement("p");
+ domUtils.setStyles(
+ p,
+ utils.isString(style) ? { "text-align": style } : style
+ );
+ var frag = tmpRange.extractContents();
+ p.appendChild(frag);
+ tmpRange.insertNode(p);
+ current = p;
+ }
+ current = domUtils.getNextDomNode(current, false, filterFn);
+ } else {
+ current = domUtils.getNextDomNode(current, true, filterFn);
+ }
+ }
+ return range.moveToBookmark(bookmark2).moveToBookmark(bookmark);
+ };
+
+ UE.commands["justify"] = {
+ execCommand: function(cmdName, align) {
+ var range = this.selection.getRange(),
+ txt;
+
+ //闭合时单独处理
+ if (range.collapsed) {
+ txt = this.document.createTextNode("p");
+ range.insertNode(txt);
+ }
+ doJustify(range, align);
+ if (txt) {
+ range.setStartBefore(txt).collapse(true);
+ domUtils.remove(txt);
+ }
+
+ range.select();
+
+ return true;
+ },
+ queryCommandValue: function() {
+ var startNode = this.selection.getStart(),
+ value = domUtils.getComputedStyle(startNode, "text-align");
+ return defaultValue[value] ? value : "left";
+ },
+ queryCommandState: function() {
+ var start = this.selection.getStart(),
+ cell =
+ start &&
+ domUtils.findParentByTagName(start, ["td", "th", "caption"], true);
+
+ return cell ? -1 : 0;
+ }
+ };
+};
+
+
+// plugins/font.js
+/**
+ * 字体颜色,背景色,字号,字体,下划线,删除线
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 字体颜色
+ * @command forecolor
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @param { String } value 色值(必须十六进制)
+ * @example
+ * ```javascript
+ * editor.execCommand( 'forecolor', '#000' );
+ * ```
+ */
+/**
+ * 返回选区字体颜色
+ * @command forecolor
+ * @method queryCommandValue
+ * @param { String } cmd 命令字符串
+ * @return { String } 返回字体颜色
+ * @example
+ * ```javascript
+ * editor.queryCommandValue( 'forecolor' );
+ * ```
+ */
+
+/**
+ * 字体背景颜色
+ * @command backcolor
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @param { String } value 色值(必须十六进制)
+ * @example
+ * ```javascript
+ * editor.execCommand( 'backcolor', '#000' );
+ * ```
+ */
+/**
+ * 返回选区字体颜色
+ * @command backcolor
+ * @method queryCommandValue
+ * @param { String } cmd 命令字符串
+ * @return { String } 返回字体背景颜色
+ * @example
+ * ```javascript
+ * editor.queryCommandValue( 'backcolor' );
+ * ```
+ */
+
+/**
+ * 字体大小
+ * @command fontsize
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @param { String } value 字体大小
+ * @example
+ * ```javascript
+ * editor.execCommand( 'fontsize', '14px' );
+ * ```
+ */
+/**
+ * 返回选区字体大小
+ * @command fontsize
+ * @method queryCommandValue
+ * @param { String } cmd 命令字符串
+ * @return { String } 返回字体大小
+ * @example
+ * ```javascript
+ * editor.queryCommandValue( 'fontsize' );
+ * ```
+ */
+
+/**
+ * 字体样式
+ * @command fontfamily
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @param { String } value 字体样式
+ * @example
+ * ```javascript
+ * editor.execCommand( 'fontfamily', '微软雅黑' );
+ * ```
+ */
+/**
+ * 返回选区字体样式
+ * @command fontfamily
+ * @method queryCommandValue
+ * @param { String } cmd 命令字符串
+ * @return { String } 返回字体样式
+ * @example
+ * ```javascript
+ * editor.queryCommandValue( 'fontfamily' );
+ * ```
+ */
+
+/**
+ * 字体下划线,与删除线互斥
+ * @command underline
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'underline' );
+ * ```
+ */
+
+/**
+ * 字体删除线,与下划线互斥
+ * @command strikethrough
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'strikethrough' );
+ * ```
+ */
+
+/**
+ * 字体边框
+ * @command fontborder
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'fontborder' );
+ * ```
+ */
+
+UE.plugins["font"] = function() {
+ var me = this,
+ fonts = {
+ forecolor: "color",
+ backcolor: "background-color",
+ fontsize: "font-size",
+ fontfamily: "font-family",
+ underline: "text-decoration",
+ strikethrough: "text-decoration",
+ fontborder: "border"
+ },
+ needCmd = { underline: 1, strikethrough: 1, fontborder: 1 },
+ needSetChild = {
+ forecolor: "color",
+ backcolor: "background-color",
+ fontsize: "font-size",
+ fontfamily: "font-family"
+ };
+ me.setOpt({
+ fontfamily: [
+ { name: "songti", val: "宋体,SimSun" },
+ { name: "yahei", val: "微软雅黑,Microsoft YaHei" },
+ { name: "kaiti", val: "楷体,楷体_GB2312, SimKai" },
+ { name: "heiti", val: "黑体, SimHei" },
+ { name: "lishu", val: "隶书, SimLi" },
+ { name: "andaleMono", val: "andale mono" },
+ { name: "arial", val: "arial, helvetica,sans-serif" },
+ { name: "arialBlack", val: "arial black,avant garde" },
+ { name: "comicSansMs", val: "comic sans ms" },
+ { name: "impact", val: "impact,chicago" },
+ { name: "timesNewRoman", val: "times new roman" }
+ ],
+ fontsize: [10, 11, 12, 14, 16, 18, 20, 24, 36]
+ });
+
+ function mergeWithParent(node) {
+ var parent;
+ while ((parent = node.parentNode)) {
+ if (
+ parent.tagName == "SPAN" &&
+ domUtils.getChildCount(parent, function(child) {
+ return !domUtils.isBookmarkNode(child) && !domUtils.isBr(child);
+ }) == 1
+ ) {
+ parent.style.cssText += node.style.cssText;
+ domUtils.remove(node, true);
+ node = parent;
+ } else {
+ break;
+ }
+ }
+ }
+ function mergeChild(rng, cmdName, value) {
+ if (needSetChild[cmdName]) {
+ rng.adjustmentBoundary();
+ if (!rng.collapsed && rng.startContainer.nodeType == 1) {
+ 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);
+ //清除冗余的代码
+ var node = range.startContainer,
+ tmp,
+ collapsed = range.collapsed;
+ while (
+ node.nodeType == 1 &&
+ domUtils.isEmptyNode(node) &&
+ dtd.$removeEmpty[node.tagName]
+ ) {
+ tmp = node.parentNode;
+ range.setStartBefore(node);
+ //trace:937
+ //更新结束边界
+ if (range.startContainer === range.endContainer) {
+ range.endOffset--;
+ }
+ domUtils.remove(node);
+ node = tmp;
+ }
+
+ if (!collapsed) {
+ node = range.endContainer;
+ while (
+ node.nodeType == 1 &&
+ domUtils.isEmptyNode(node) &&
+ dtd.$removeEmpty[node.tagName]
+ ) {
+ tmp = node.parentNode;
+ range.setEndBefore(node);
+ domUtils.remove(node);
+
+ node = tmp;
+ }
+ }
+ }
+
+ range = this.selection.getRange();
+ doRemove(range);
+ range.select();
+ }
+ };
+};
+
+
+// plugins/blockquote.js
+/**
+ * 添加引用
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 添加引用
+ * @command blockquote
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'blockquote' );
+ * ```
+ */
+
+/**
+ * 添加引用
+ * @command blockquote
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @param { Object } attrs 节点属性
+ * @example
+ * ```javascript
+ * editor.execCommand( 'blockquote',{
+ * style: "color: red;"
+ * } );
+ * ```
+ */
+
+UE.plugins["blockquote"] = function() {
+ var me = this;
+ function getObj(editor) {
+ return domUtils.filterNodeList(
+ editor.selection.getStartElementPath(),
+ "blockquote"
+ );
+ }
+ me.commands["blockquote"] = {
+ execCommand: function(cmdName, attrs) {
+ var range = this.selection.getRange(),
+ obj = getObj(this),
+ blockquote = dtd.blockquote,
+ bookmark = range.createBookmark();
+
+ if (obj) {
+ var start = range.startContainer,
+ startBlock = domUtils.isBlockElm(start)
+ ? start
+ : domUtils.findParent(start, function(node) {
+ return domUtils.isBlockElm(node);
+ }),
+ end = range.endContainer,
+ endBlock = domUtils.isBlockElm(end)
+ ? end
+ : domUtils.findParent(end, function(node) {
+ return domUtils.isBlockElm(node);
+ });
+
+ //处理一下li
+ startBlock =
+ domUtils.findParentByTagName(startBlock, "li", true) || startBlock;
+ endBlock =
+ domUtils.findParentByTagName(endBlock, "li", true) || endBlock;
+
+ if (
+ startBlock.tagName == "LI" ||
+ startBlock.tagName == "TD" ||
+ startBlock === obj ||
+ domUtils.isBody(startBlock)
+ ) {
+ domUtils.remove(obj, true);
+ } else {
+ domUtils.breakParent(startBlock, obj);
+ }
+
+ if (startBlock !== endBlock) {
+ obj = domUtils.findParentByTagName(endBlock, "blockquote");
+ if (obj) {
+ if (
+ endBlock.tagName == "LI" ||
+ endBlock.tagName == "TD" ||
+ domUtils.isBody(endBlock)
+ ) {
+ obj.parentNode && domUtils.remove(obj, true);
+ } else {
+ domUtils.breakParent(endBlock, obj);
+ }
+ }
+ }
+
+ var blockquotes = domUtils.getElementsByTagName(
+ this.document,
+ "blockquote"
+ );
+ for (var i = 0, bi; (bi = blockquotes[i++]); ) {
+ if (!bi.childNodes.length) {
+ domUtils.remove(bi);
+ } else if (
+ domUtils.getPosition(bi, startBlock) &
+ domUtils.POSITION_FOLLOWING &&
+ domUtils.getPosition(bi, endBlock) & domUtils.POSITION_PRECEDING
+ ) {
+ domUtils.remove(bi, true);
+ }
+ }
+ } else {
+ var tmpRange = range.cloneRange(),
+ node = tmpRange.startContainer.nodeType == 1
+ ? tmpRange.startContainer
+ : tmpRange.startContainer.parentNode,
+ preNode = node,
+ doEnd = 1;
+
+ //调整开始
+ while (1) {
+ if (domUtils.isBody(node)) {
+ if (preNode !== node) {
+ if (range.collapsed) {
+ tmpRange.selectNode(preNode);
+ doEnd = 0;
+ } else {
+ tmpRange.setStartBefore(preNode);
+ }
+ } else {
+ tmpRange.setStart(node, 0);
+ }
+
+ break;
+ }
+ if (!blockquote[node.tagName]) {
+ if (range.collapsed) {
+ tmpRange.selectNode(preNode);
+ } else {
+ tmpRange.setStartBefore(preNode);
+ }
+ break;
+ }
+
+ preNode = node;
+ node = node.parentNode;
+ }
+
+ //调整结束
+ if (doEnd) {
+ preNode = node = node = tmpRange.endContainer.nodeType == 1
+ ? tmpRange.endContainer
+ : tmpRange.endContainer.parentNode;
+ while (1) {
+ if (domUtils.isBody(node)) {
+ if (preNode !== node) {
+ tmpRange.setEndAfter(preNode);
+ } else {
+ tmpRange.setEnd(node, node.childNodes.length);
+ }
+
+ break;
+ }
+ if (!blockquote[node.tagName]) {
+ tmpRange.setEndAfter(preNode);
+ break;
+ }
+
+ preNode = node;
+ node = node.parentNode;
+ }
+ }
+
+ node = range.document.createElement("blockquote");
+ domUtils.setAttributes(node, attrs);
+ node.appendChild(tmpRange.extractContents());
+ tmpRange.insertNode(node);
+ //去除重复的
+ var childs = domUtils.getElementsByTagName(node, "blockquote");
+ for (var i = 0, ci; (ci = childs[i++]); ) {
+ if (ci.parentNode) {
+ domUtils.remove(ci, true);
+ }
+ }
+ }
+ range.moveToBookmark(bookmark).select();
+ },
+ queryCommandState: function() {
+ return getObj(this) ? 1 : 0;
+ }
+ };
+};
+
+
+// plugins/convertcase.js
+/**
+ * 大小写转换
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 把选区内文本变大写,与“tolowercase”命令互斥
+ * @command touppercase
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'touppercase' );
+ * ```
+ */
+
+/**
+ * 把选区内文本变小写,与“touppercase”命令互斥
+ * @command tolowercase
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'tolowercase' );
+ * ```
+ */
+UE.commands["touppercase"] = UE.commands["tolowercase"] = {
+ execCommand: function(cmd) {
+ var me = this;
+ var rng = me.selection.getRange();
+ if (rng.collapsed) {
+ return rng;
+ }
+ var bk = rng.createBookmark(),
+ bkEnd = bk.end,
+ filterFn = function(node) {
+ return !domUtils.isBr(node) && !domUtils.isWhitespace(node);
+ },
+ curNode = domUtils.getNextDomNode(bk.start, false, filterFn);
+ while (
+ curNode &&
+ domUtils.getPosition(curNode, bkEnd) & domUtils.POSITION_PRECEDING
+ ) {
+ if (curNode.nodeType == 3) {
+ curNode.nodeValue = curNode.nodeValue[
+ cmd == "touppercase" ? "toUpperCase" : "toLowerCase"
+ ]();
+ }
+ curNode = domUtils.getNextDomNode(curNode, true, filterFn);
+ if (curNode === bkEnd) {
+ break;
+ }
+ }
+ rng.moveToBookmark(bk).select();
+ }
+};
+
+
+// plugins/indent.js
+/**
+ * 首行缩进
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 缩进
+ * @command indent
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'indent' );
+ * ```
+ */
+UE.commands["indent"] = {
+ execCommand: function() {
+ var me = this,
+ value = me.queryCommandState("indent")
+ ? "0em"
+ : me.options.indentValue || "2em";
+ me.execCommand("Paragraph", "p", { style: "text-indent:" + value });
+ },
+ queryCommandState: function() {
+ var pN = domUtils.filterNodeList(
+ this.selection.getStartElementPath(),
+ "p h1 h2 h3 h4 h5 h6"
+ );
+ return pN && pN.style.textIndent && parseInt(pN.style.textIndent) ? 1 : 0;
+ }
+};
+
+
+// plugins/print.js
+/**
+ * 打印
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 打印
+ * @command print
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'print' );
+ * ```
+ */
+UE.commands["print"] = {
+ execCommand: function() {
+ this.window.print();
+ },
+ notNeedUndo: 1
+};
+
+
+// plugins/preview.js
+/**
+ * 预览
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 预览
+ * @command preview
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'preview' );
+ * ```
+ */
+UE.commands["preview"] = {
+ execCommand: function() {
+ var w = window.open("", "_blank", ""),
+ d = w.document;
+ d.open();
+ d.write(
+ '" +
+ this.getContent(null, null, true) +
+ " "
+ );
+ d.close();
+ },
+ notNeedUndo: 1
+};
+
+
+// plugins/selectall.js
+/**
+ * 全选
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 选中所有内容
+ * @command selectall
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'selectall' );
+ * ```
+ */
+UE.plugins["selectall"] = function() {
+ var me = this;
+ me.commands["selectall"] = {
+ execCommand: function() {
+ //去掉了原生的selectAll,因为会出现报错和当内容为空时,不能出现闭合状态的光标
+ var me = this,
+ body = me.body,
+ range = me.selection.getRange();
+ range.selectNodeContents(body);
+ if (domUtils.isEmptyBlock(body)) {
+ //opera不能自动合并到元素的里边,要手动处理一下
+ if (browser.opera && body.firstChild && body.firstChild.nodeType == 1) {
+ range.setStartAtFirst(body.firstChild);
+ }
+ range.collapse(true);
+ }
+ range.select(true);
+ },
+ notNeedUndo: 1
+ };
+
+ //快捷键
+ me.addshortcutkey({
+ selectAll: "ctrl+65"
+ });
+};
+
+
+// plugins/paragraph.js
+/**
+ * 段落样式
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 段落格式
+ * @command paragraph
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @param {String} style 标签值为:'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'
+ * @param {Object} attrs 标签的属性
+ * @example
+ * ```javascript
+ * editor.execCommand( 'Paragraph','h1','{
+ * class:'test'
+ * }' );
+ * ```
+ */
+
+/**
+ * 返回选区内节点标签名
+ * @command paragraph
+ * @method queryCommandValue
+ * @param { String } cmd 命令字符串
+ * @return { String } 节点标签名
+ * @example
+ * ```javascript
+ * editor.queryCommandValue( 'Paragraph' );
+ * ```
+ */
+
+UE.plugins["paragraph"] = function () {
+ var me = this,
+ block = domUtils.isBlockElm,
+ notExchange = ["TD", "LI", "PRE"],
+ doParagraph = function (range, style, attrs, sourceCmdName) {
+ var bookmark = range.createBookmark(),
+ filterFn = function (node) {
+ return node.nodeType == 1
+ ? node.tagName.toLowerCase() != "br" &&
+ !domUtils.isBookmarkNode(node)
+ : !domUtils.isWhitespace(node);
+ },
+ para;
+
+ range.enlarge(true);
+ var bookmark2 = range.createBookmark(),
+ current = domUtils.getNextDomNode(bookmark2.start, false, filterFn),
+ tmpRange = range.cloneRange(),
+ tmpNode;
+ while (
+ current &&
+ !(
+ domUtils.getPosition(current, bookmark2.end) &
+ domUtils.POSITION_FOLLOWING
+ )
+ ) {
+ if (current.nodeType == 3 || !block(current)) {
+ tmpRange.setStartBefore(current);
+ while (current && current !== bookmark2.end && !block(current)) {
+ tmpNode = current;
+ current = domUtils.getNextDomNode(current, false, null, function (
+ node
+ ) {
+ return !block(node);
+ });
+ }
+ tmpRange.setEndAfter(tmpNode);
+
+ para = range.document.createElement(style);
+ if (attrs) {
+ domUtils.setAttributes(para, attrs);
+ if (
+ sourceCmdName &&
+ sourceCmdName == "customstyle" &&
+ attrs.style
+ ) {
+ para.style.cssText = attrs.style;
+ }
+ }
+ para.appendChild(tmpRange.extractContents());
+ //需要内容占位
+ if (domUtils.isEmptyNode(para)) {
+ domUtils.fillChar(range.document, para);
+ }
+
+ tmpRange.insertNode(para);
+
+ var parent = para.parentNode;
+ //如果para上一级是一个block元素且不是body,td就删除它
+ if (
+ block(parent) &&
+ !domUtils.isBody(para.parentNode) &&
+ utils.indexOf(notExchange, parent.tagName) == -1
+ ) {
+ //存储dir,style
+ if (!(sourceCmdName && sourceCmdName == "customstyle")) {
+ parent.getAttribute("dir") &&
+ para.setAttribute("dir", parent.getAttribute("dir"));
+ //trace:1070
+ parent.style.cssText &&
+ (para.style.cssText =
+ parent.style.cssText + ";" + para.style.cssText);
+ //trace:1030
+ parent.style.textAlign &&
+ !para.style.textAlign &&
+ (para.style.textAlign = parent.style.textAlign);
+ parent.style.textIndent &&
+ !para.style.textIndent &&
+ (para.style.textIndent = parent.style.textIndent);
+ parent.style.padding &&
+ !para.style.padding &&
+ (para.style.padding = parent.style.padding);
+ }
+
+ //trace:1706 选择的就是h1-6要删除
+ if (
+ attrs &&
+ /h\d/i.test(parent.tagName) &&
+ !/h\d/i.test(para.tagName)
+ ) {
+ domUtils.setAttributes(parent, attrs);
+ if (
+ sourceCmdName &&
+ sourceCmdName == "customstyle" &&
+ attrs.style
+ ) {
+ parent.style.cssText = attrs.style;
+ }
+ domUtils.remove(para, true);
+ para = parent;
+ } else {
+ domUtils.remove(para.parentNode, true);
+ }
+ }
+
+ if (utils.indexOf(notExchange, parent.tagName) != -1) {
+ current = parent;
+ } else {
+ current = para;
+ }
+
+ current = domUtils.getNextDomNode(current, false, filterFn);
+ } else {
+ current = domUtils.getNextDomNode(current, true, filterFn);
+ }
+ }
+ return range.moveToBookmark(bookmark2).moveToBookmark(bookmark);
+ };
+ me.setOpt("paragraph", {
+ p: "",
+ h1: "",
+ h2: "",
+ h3: "",
+ h4: "",
+ h5: "",
+ h6: ""
+ });
+ me.commands["paragraph"] = {
+ execCommand: function (cmdName, style, attrs, sourceCmdName) {
+ var range = this.selection.getRange();
+ //闭合时单独处理
+ if (range.collapsed) {
+ var txt = this.document.createTextNode("p");
+ range.insertNode(txt);
+ //去掉冗余的fillchar
+ if (browser.ie) {
+ var node = txt.previousSibling;
+ if (node && domUtils.isWhitespace(node)) {
+ domUtils.remove(node);
+ }
+ node = txt.nextSibling;
+ if (node && domUtils.isWhitespace(node)) {
+ domUtils.remove(node);
+ }
+ }
+ }
+ range = doParagraph(range, style, attrs, sourceCmdName);
+ if (txt) {
+ range.setStartBefore(txt).collapse(true);
+ pN = txt.parentNode;
+
+ domUtils.remove(txt);
+
+ if (domUtils.isBlockElm(pN) && domUtils.isEmptyNode(pN)) {
+ domUtils.fillNode(this.document, pN);
+ }
+ }
+
+ if (
+ browser.gecko &&
+ range.collapsed &&
+ range.startContainer.nodeType == 1
+ ) {
+ var child = range.startContainer.childNodes[range.startOffset];
+ if (
+ child &&
+ child.nodeType == 1 &&
+ child.tagName.toLowerCase() == style
+ ) {
+ range.setStart(child, 0).collapse(true);
+ }
+ }
+ //trace:1097 原来有true,原因忘了,但去了就不能清除多余的占位符了
+ range.select();
+
+ return true;
+ },
+ queryCommandValue: function () {
+ var node = domUtils.filterNodeList(
+ this.selection.getStartElementPath(),
+ "p h1 h2 h3 h4 h5 h6"
+ );
+ return node ? node.tagName.toLowerCase() : "";
+ }
+ };
+};
+
+
+// plugins/directionality.js
+/**
+ * 设置文字输入的方向的插件
+ * @file
+ * @since 1.2.6.1
+ */
+;(function() {
+ var block = domUtils.isBlockElm,
+ getObj = function(editor) {
+ // var startNode = editor.selection.getStart(),
+ // parents;
+ // if ( startNode ) {
+ // //查找所有的是block的父亲节点
+ // parents = domUtils.findParents( startNode, true, block, true );
+ // for ( var i = 0,ci; ci = parents[i++]; ) {
+ // if ( ci.getAttribute( 'dir' ) ) {
+ // return ci;
+ // }
+ // }
+ // }
+ return domUtils.filterNodeList(
+ editor.selection.getStartElementPath(),
+ function(n) {
+ return n && n.nodeType == 1 && n.getAttribute("dir");
+ }
+ );
+ },
+ doDirectionality = function(range, editor, forward) {
+ var bookmark,
+ filterFn = function(node) {
+ return node.nodeType == 1
+ ? !domUtils.isBookmarkNode(node)
+ : !domUtils.isWhitespace(node);
+ },
+ obj = getObj(editor);
+
+ if (obj && range.collapsed) {
+ obj.setAttribute("dir", forward);
+ return range;
+ }
+ bookmark = range.createBookmark();
+ range.enlarge(true);
+ var bookmark2 = range.createBookmark(),
+ current = domUtils.getNextDomNode(bookmark2.start, false, filterFn),
+ tmpRange = range.cloneRange(),
+ tmpNode;
+ while (
+ current &&
+ !(
+ domUtils.getPosition(current, bookmark2.end) &
+ domUtils.POSITION_FOLLOWING
+ )
+ ) {
+ if (current.nodeType == 3 || !block(current)) {
+ tmpRange.setStartBefore(current);
+ while (current && current !== bookmark2.end && !block(current)) {
+ tmpNode = current;
+ current = domUtils.getNextDomNode(current, false, null, function(
+ node
+ ) {
+ return !block(node);
+ });
+ }
+ tmpRange.setEndAfter(tmpNode);
+ var common = tmpRange.getCommonAncestor();
+ if (!domUtils.isBody(common) && block(common)) {
+ //遍历到了block节点
+ common.setAttribute("dir", forward);
+ current = common;
+ } else {
+ //没有遍历到,添加一个block节点
+ var p = range.document.createElement("p");
+ p.setAttribute("dir", forward);
+ var frag = tmpRange.extractContents();
+ p.appendChild(frag);
+ tmpRange.insertNode(p);
+ current = p;
+ }
+
+ current = domUtils.getNextDomNode(current, false, filterFn);
+ } else {
+ current = domUtils.getNextDomNode(current, true, filterFn);
+ }
+ }
+ return range.moveToBookmark(bookmark2).moveToBookmark(bookmark);
+ };
+
+ /**
+ * 文字输入方向
+ * @command directionality
+ * @method execCommand
+ * @param { String } cmdName 命令字符串
+ * @param { String } forward 传入'ltr'表示从左向右输入,传入'rtl'表示从右向左输入
+ * @example
+ * ```javascript
+ * editor.execCommand( 'directionality', 'ltr');
+ * ```
+ */
+
+ /**
+ * 查询当前选区的文字输入方向
+ * @command directionality
+ * @method queryCommandValue
+ * @param { String } cmdName 命令字符串
+ * @return { String } 返回'ltr'表示从左向右输入,返回'rtl'表示从右向左输入
+ * @example
+ * ```javascript
+ * editor.queryCommandValue( 'directionality');
+ * ```
+ */
+ UE.commands["directionality"] = {
+ execCommand: function(cmdName, forward) {
+ var range = this.selection.getRange();
+ //闭合时单独处理
+ if (range.collapsed) {
+ var txt = this.document.createTextNode("d");
+ range.insertNode(txt);
+ }
+ doDirectionality(range, this, forward);
+ if (txt) {
+ range.setStartBefore(txt).collapse(true);
+ domUtils.remove(txt);
+ }
+
+ range.select();
+ return true;
+ },
+ queryCommandValue: function() {
+ var node = getObj(this);
+ return node ? node.getAttribute("dir") : "ltr";
+ }
+ };
+})();
+
+
+// plugins/horizontal.js
+/**
+ * 插入分割线插件
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 插入分割线
+ * @command horizontal
+ * @method execCommand
+ * @param { String } cmdName 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'horizontal' );
+ * ```
+ */
+UE.plugins["horizontal"] = function() {
+ var me = this;
+ me.commands["horizontal"] = {
+ execCommand: function(cmdName) {
+ var me = this;
+ if (me.queryCommandState(cmdName) !== -1) {
+ me.execCommand("insertHtml", " ");
+ var range = me.selection.getRange(),
+ start = range.startContainer;
+ if (start.nodeType == 1 && !start.childNodes[range.startOffset]) {
+ var tmp;
+ if ((tmp = start.childNodes[range.startOffset - 1])) {
+ if (tmp.nodeType == 1 && tmp.tagName == "HR") {
+ if (me.options.enterTag == "p") {
+ tmp = me.document.createElement("p");
+ range.insertNode(tmp);
+ range.setStart(tmp, 0).setCursor();
+ } else {
+ tmp = me.document.createElement("br");
+ range.insertNode(tmp);
+ range.setStartBefore(tmp).setCursor();
+ }
+ }
+ }
+ }
+ return true;
+ }
+ },
+ //边界在table里不能加分隔线
+ queryCommandState: function() {
+ return domUtils.filterNodeList(
+ this.selection.getStartElementPath(),
+ "table"
+ )
+ ? -1
+ : 0;
+ }
+ };
+ // me.addListener('delkeyup',function(){
+ // var rng = this.selection.getRange();
+ // if(browser.ie && browser.version > 8){
+ // rng.txtToElmBoundary(true);
+ // if(domUtils.isStartInblock(rng)){
+ // var tmpNode = rng.startContainer;
+ // var pre = tmpNode.previousSibling;
+ // if(pre && domUtils.isTagNode(pre,'hr')){
+ // domUtils.remove(pre);
+ // rng.select();
+ // return;
+ // }
+ // }
+ // }
+ // if(domUtils.isBody(rng.startContainer)){
+ // var hr = rng.startContainer.childNodes[rng.startOffset -1];
+ // if(hr && hr.nodeName == 'HR'){
+ // var next = hr.nextSibling;
+ // if(next){
+ // rng.setStart(next,0)
+ // }else if(hr.previousSibling){
+ // rng.setStartAtLast(hr.previousSibling)
+ // }else{
+ // var p = this.document.createElement('p');
+ // hr.parentNode.insertBefore(p,hr);
+ // domUtils.fillNode(this.document,p);
+ // rng.setStart(p,0);
+ // }
+ // domUtils.remove(hr);
+ // rng.setCursor(false,true);
+ // }
+ // }
+ // })
+ me.addListener("delkeydown", function(name, evt) {
+ var rng = this.selection.getRange();
+ rng.txtToElmBoundary(true);
+ if (domUtils.isStartInblock(rng)) {
+ var tmpNode = rng.startContainer;
+ var pre = tmpNode.previousSibling;
+ if (pre && domUtils.isTagNode(pre, "hr")) {
+ domUtils.remove(pre);
+ rng.select();
+ domUtils.preventDefault(evt);
+ return true;
+ }
+ }
+ });
+};
+
+
+// plugins/time.js
+/**
+ * 插入时间和日期
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 插入时间,默认格式:12:59:59
+ * @command time
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'time');
+ * ```
+ */
+
+/**
+ * 插入日期,默认格式:2013-08-30
+ * @command date
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'date');
+ * ```
+ */
+UE.commands["time"] = UE.commands["date"] = {
+ execCommand: function(cmd, format) {
+ var date = new Date();
+
+ function formatTime(date, format) {
+ var hh = ("0" + date.getHours()).slice(-2),
+ ii = ("0" + date.getMinutes()).slice(-2),
+ ss = ("0" + date.getSeconds()).slice(-2);
+ format = format || "hh:ii:ss";
+ return format.replace(/hh/gi, hh).replace(/ii/gi, ii).replace(/ss/gi, ss);
+ }
+ function formatDate(date, format) {
+ var yyyy = ("000" + date.getFullYear()).slice(-4),
+ yy = yyyy.slice(-2),
+ mm = ("0" + (date.getMonth() + 1)).slice(-2),
+ dd = ("0" + date.getDate()).slice(-2);
+ format = format || "yyyy-mm-dd";
+ return format
+ .replace(/yyyy/gi, yyyy)
+ .replace(/yy/gi, yy)
+ .replace(/mm/gi, mm)
+ .replace(/dd/gi, dd);
+ }
+
+ this.execCommand(
+ "insertHtml",
+ cmd == "time" ? formatTime(date, format) : formatDate(date, format)
+ );
+ }
+};
+
+
+// plugins/rowspacing.js
+/**
+ * 段前段后间距插件
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 设置段间距
+ * @command rowspacing
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @param { String } value 段间距的值,以px为单位
+ * @param { String } dir 间距位置,top或bottom,分别表示段前和段后
+ * @example
+ * ```javascript
+ * editor.execCommand( 'rowspacing', '10', 'top' );
+ * ```
+ */
+
+UE.plugins["rowspacing"] = function() {
+ var me = this;
+ me.setOpt({
+ rowspacingtop: ["5", "10", "15", "20", "25"],
+ rowspacingbottom: ["5", "10", "15", "20", "25"]
+ });
+ me.commands["rowspacing"] = {
+ execCommand: function(cmdName, value, dir) {
+ this.execCommand("paragraph", "p", {
+ style: "margin-" + dir + ":" + value + "px"
+ });
+ return true;
+ },
+ queryCommandValue: function(cmdName, dir) {
+ var pN = domUtils.filterNodeList(
+ this.selection.getStartElementPath(),
+ function(node) {
+ return domUtils.isBlockElm(node);
+ }
+ ),
+ value;
+ //trace:1026
+ if (pN) {
+ value = domUtils
+ .getComputedStyle(pN, "margin-" + dir)
+ .replace(/[^\d]/g, "");
+ return !value ? 0 : value;
+ }
+ return 0;
+ }
+ };
+};
+
+
+// plugins/lineheight.js
+/**
+ * 设置行内间距
+ * @file
+ * @since 1.2.6.1
+ */
+UE.plugins["lineheight"] = function() {
+ var me = this;
+ me.setOpt({ lineheight: ["1", "1.5", "1.75", "2", "3", "4", "5"] });
+
+ /**
+ * 行距
+ * @command lineheight
+ * @method execCommand
+ * @param { String } cmdName 命令字符串
+ * @param { String } value 传入的行高值, 该值是当前字体的倍数, 例如: 1.5, 1.75
+ * @example
+ * ```javascript
+ * editor.execCommand( 'lineheight', 1.5);
+ * ```
+ */
+ /**
+ * 查询当前选区内容的行高大小
+ * @command lineheight
+ * @method queryCommandValue
+ * @param { String } cmd 命令字符串
+ * @return { String } 返回当前行高大小
+ * @example
+ * ```javascript
+ * editor.queryCommandValue( 'lineheight' );
+ * ```
+ */
+
+ me.commands["lineheight"] = {
+ execCommand: function(cmdName, value) {
+ this.execCommand("paragraph", "p", {
+ style: "line-height:" + (value == "1" ? "normal" : value + "em")
+ });
+ return true;
+ },
+ queryCommandValue: function() {
+ var pN = domUtils.filterNodeList(
+ this.selection.getStartElementPath(),
+ function(node) {
+ return domUtils.isBlockElm(node);
+ }
+ );
+ if (pN) {
+ var value = domUtils.getComputedStyle(pN, "line-height");
+ return value == "normal" ? 1 : value.replace(/[^\d.]*/gi, "");
+ }
+ }
+ };
+};
+
+
+// plugins/insertcode.js
+/**
+ * 插入代码插件
+ * @file
+ * @since 1.2.6.1
+ */
+
+UE.plugins["insertcode"] = function() {
+ var me = this;
+ me.ready(function() {
+ utils.cssRule(
+ "pre",
+ "pre{margin:.5em 0;padding:.4em .6em;border-radius:8px;background:#f8f8f8;}",
+ me.document
+ );
+ });
+ me.setOpt("insertcode", {
+ as3: "ActionScript3",
+ bash: "Bash/Shell",
+ cpp: "C/C++",
+ css: "Css",
+ cf: "CodeFunction",
+ "c#": "C#",
+ delphi: "Delphi",
+ diff: "Diff",
+ erlang: "Erlang",
+ groovy: "Groovy",
+ html: "Html",
+ java: "Java",
+ jfx: "JavaFx",
+ js: "Javascript",
+ pl: "Perl",
+ php: "Php",
+ plain: "Plain Text",
+ ps: "PowerShell",
+ python: "Python",
+ ruby: "Ruby",
+ scala: "Scala",
+ sql: "Sql",
+ vb: "Vb",
+ xml: "Xml"
+ });
+
+ /**
+ * 插入代码
+ * @command insertcode
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @param { String } lang 插入代码的语言
+ * @example
+ * ```javascript
+ * editor.execCommand( 'insertcode', 'javascript' );
+ * ```
+ */
+
+ /**
+ * 如果选区所在位置是插入插入代码区域,返回代码的语言
+ * @command insertcode
+ * @method queryCommandValue
+ * @param { String } cmd 命令字符串
+ * @return { String } 返回代码的语言
+ * @example
+ * ```javascript
+ * editor.queryCommandValue( 'insertcode' );
+ * ```
+ */
+
+ me.commands["insertcode"] = {
+ execCommand: function(cmd, lang) {
+ var me = this,
+ rng = me.selection.getRange(),
+ pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);
+ if (pre) {
+ pre.className = "brush:" + lang + ";toolbar:false;";
+ } else {
+ var code = "";
+ if (rng.collapsed) {
+ code = browser.ie && browser.ie11below
+ ? browser.version <= 8 ? " " : ""
+ : " ";
+ } else {
+ var frag = rng.extractContents();
+ var div = me.document.createElement("div");
+ div.appendChild(frag);
+
+ utils.each(
+ UE.filterNode(
+ UE.htmlparser(div.innerHTML.replace(/[\r\t]/g, "")),
+ me.options.filterTxtRules
+ ).children,
+ function(node) {
+ if (browser.ie && browser.ie11below && browser.version > 8) {
+ if (node.type == "element") {
+ if (node.tagName == "br") {
+ code += "\n";
+ } else if (!dtd.$empty[node.tagName]) {
+ utils.each(node.children, function(cn) {
+ if (cn.type == "element") {
+ if (cn.tagName == "br") {
+ code += "\n";
+ } else if (!dtd.$empty[node.tagName]) {
+ code += cn.innerText();
+ }
+ } else {
+ code += cn.data;
+ }
+ });
+ if (!/\n$/.test(code)) {
+ code += "\n";
+ }
+ }
+ } else {
+ code += node.data + "\n";
+ }
+ if (!node.nextSibling() && /\n$/.test(code)) {
+ code = code.replace(/\n$/, "");
+ }
+ } else {
+ if (browser.ie && browser.ie11below) {
+ if (node.type == "element") {
+ if (node.tagName == "br") {
+ code += " ";
+ } else if (!dtd.$empty[node.tagName]) {
+ utils.each(node.children, function(cn) {
+ if (cn.type == "element") {
+ if (cn.tagName == "br") {
+ code += " ";
+ } else if (!dtd.$empty[node.tagName]) {
+ code += cn.innerText();
+ }
+ } else {
+ code += cn.data;
+ }
+ });
+ if (!/br>$/.test(code)) {
+ code += " ";
+ }
+ }
+ } else {
+ code += node.data + " ";
+ }
+ if (!node.nextSibling() && / $/.test(code)) {
+ code = code.replace(/ $/, "");
+ }
+ } else {
+ code += node.type == "element"
+ ? dtd.$empty[node.tagName] ? "" : node.innerText()
+ : node.data;
+ if (!/br\/?\s*>$/.test(code)) {
+ if (!node.nextSibling()) return;
+ code += " ";
+ }
+ }
+ }
+ }
+ );
+ }
+ me.execCommand(
+ "inserthtml",
+ '' +
+ code +
+ " ",
+ true
+ );
+
+ pre = me.document.getElementById("coder");
+ domUtils.removeAttributes(pre, "id");
+ var tmpNode = pre.previousSibling;
+
+ if (
+ tmpNode &&
+ ((tmpNode.nodeType == 3 &&
+ tmpNode.nodeValue.length == 1 &&
+ browser.ie &&
+ browser.version == 6) ||
+ domUtils.isEmptyBlock(tmpNode))
+ ) {
+ domUtils.remove(tmpNode);
+ }
+ var rng = me.selection.getRange();
+ if (domUtils.isEmptyBlock(pre)) {
+ rng.setStart(pre, 0).setCursor(false, true);
+ } else {
+ rng.selectNodeContents(pre).select();
+ }
+ }
+ },
+ queryCommandValue: function() {
+ var path = this.selection.getStartElementPath();
+ var lang = "";
+ utils.each(path, function(node) {
+ if (node.nodeName == "PRE") {
+ var match = node.className.match(/brush:([^;]+)/);
+ lang = match && match[1] ? match[1] : "";
+ return false;
+ }
+ });
+ return lang;
+ }
+ };
+
+ me.addInputRule(function(root) {
+ utils.each(root.getNodesByTagName("pre"), function(pre) {
+ var brs = pre.getNodesByTagName("br");
+ if (brs.length) {
+ browser.ie &&
+ browser.ie11below &&
+ browser.version > 8 &&
+ utils.each(brs, function(br) {
+ var txt = UE.uNode.createText("\n");
+ br.parentNode.insertBefore(txt, br);
+ br.parentNode.removeChild(br);
+ });
+ return;
+ }
+ if (browser.ie && browser.ie11below && browser.version > 8) return;
+ var code = pre.innerText().split(/\n/);
+ pre.innerHTML("");
+ utils.each(code, function(c) {
+ if (c.length) {
+ pre.appendChild(UE.uNode.createText(c));
+ }
+ pre.appendChild(UE.uNode.createElement("br"));
+ });
+ });
+ });
+ me.addOutputRule(function(root) {
+ utils.each(root.getNodesByTagName("pre"), function(pre) {
+ var code = "";
+ utils.each(pre.children, function(n) {
+ if (n.type == "text") {
+ //在ie下文本内容有可能末尾带有\n要去掉
+ //trace:3396
+ code += n.data.replace(/[ ]/g, " ").replace(/\n$/, "");
+ } else {
+ if (n.tagName == "br") {
+ code += "\n";
+ } else {
+ code += !dtd.$empty[n.tagName] ? "" : n.innerText();
+ }
+ }
+ });
+
+ pre.innerText(code.replace(/( |\n)+$/, ""));
+ });
+ });
+ //不需要判断highlight的command列表
+ me.notNeedCodeQuery = {
+ help: 1,
+ undo: 1,
+ redo: 1,
+ source: 1,
+ print: 1,
+ searchreplace: 1,
+ fullscreen: 1,
+ preview: 1,
+ insertparagraph: 1,
+ elementpath: 1,
+ insertcode: 1,
+ inserthtml: 1,
+ selectall: 1
+ };
+ //将queyCommamndState重置
+ var orgQuery = me.queryCommandState;
+ me.queryCommandState = function(cmd) {
+ var me = this;
+
+ if (
+ !me.notNeedCodeQuery[cmd.toLowerCase()] &&
+ me.selection &&
+ me.queryCommandValue("insertcode")
+ ) {
+ return -1;
+ }
+ return UE.Editor.prototype.queryCommandState.apply(this, arguments);
+ };
+ me.addListener("beforeenterkeydown", function() {
+ var rng = me.selection.getRange();
+ var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);
+ if (pre) {
+ me.fireEvent("saveScene");
+ if (!rng.collapsed) {
+ rng.deleteContents();
+ }
+ if (!browser.ie || browser.ie9above) {
+ var tmpNode = me.document.createElement("br"),
+ pre;
+ rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true);
+ var next = tmpNode.nextSibling;
+ if (!next && (!browser.ie || browser.version > 10)) {
+ rng.insertNode(tmpNode.cloneNode(false));
+ } else {
+ rng.setStartAfter(tmpNode);
+ }
+ pre = tmpNode.previousSibling;
+ var tmp;
+ while (pre) {
+ tmp = pre;
+ pre = pre.previousSibling;
+ if (!pre || pre.nodeName == "BR") {
+ pre = tmp;
+ break;
+ }
+ }
+ if (pre) {
+ var str = "";
+ while (
+ pre &&
+ pre.nodeName != "BR" &&
+ new RegExp("^[\\s" + domUtils.fillChar + "]*$").test(pre.nodeValue)
+ ) {
+ str += pre.nodeValue;
+ pre = pre.nextSibling;
+ }
+ if (pre.nodeName != "BR") {
+ var match = pre.nodeValue.match(
+ new RegExp("^([\\s" + domUtils.fillChar + "]+)")
+ );
+ if (match && match[1]) {
+ str += match[1];
+ }
+ }
+ if (str) {
+ str = me.document.createTextNode(str);
+ rng.insertNode(str).setStartAfter(str);
+ }
+ }
+ rng.collapse(true).select(true);
+ } else {
+ if (browser.version > 8) {
+ var txt = me.document.createTextNode("\n");
+ var start = rng.startContainer;
+ if (rng.startOffset == 0) {
+ var preNode = start.previousSibling;
+ if (preNode) {
+ rng.insertNode(txt);
+ var fillchar = me.document.createTextNode(" ");
+ rng
+ .setStartAfter(txt)
+ .insertNode(fillchar)
+ .setStart(fillchar, 0)
+ .collapse(true)
+ .select(true);
+ }
+ } else {
+ rng.insertNode(txt).setStartAfter(txt);
+ var fillchar = me.document.createTextNode(" ");
+ start = rng.startContainer.childNodes[rng.startOffset];
+ if (start && !/^\n/.test(start.nodeValue)) {
+ rng.setStartBefore(txt);
+ }
+ rng
+ .insertNode(fillchar)
+ .setStart(fillchar, 0)
+ .collapse(true)
+ .select(true);
+ }
+ } else {
+ var tmpNode = me.document.createElement("br");
+ rng.insertNode(tmpNode);
+ rng.insertNode(me.document.createTextNode(domUtils.fillChar));
+ rng.setStartAfter(tmpNode);
+ pre = tmpNode.previousSibling;
+ var tmp;
+ while (pre) {
+ tmp = pre;
+ pre = pre.previousSibling;
+ if (!pre || pre.nodeName == "BR") {
+ pre = tmp;
+ break;
+ }
+ }
+ if (pre) {
+ var str = "";
+ while (
+ pre &&
+ pre.nodeName != "BR" &&
+ new RegExp("^[ " + domUtils.fillChar + "]*$").test(pre.nodeValue)
+ ) {
+ str += pre.nodeValue;
+ pre = pre.nextSibling;
+ }
+ if (pre.nodeName != "BR") {
+ var match = pre.nodeValue.match(
+ new RegExp("^([ " + domUtils.fillChar + "]+)")
+ );
+ if (match && match[1]) {
+ str += match[1];
+ }
+ }
+
+ str = me.document.createTextNode(str);
+ rng.insertNode(str).setStartAfter(str);
+ }
+ rng.collapse(true).select();
+ }
+ }
+ me.fireEvent("saveScene");
+ return true;
+ }
+ });
+
+ me.addListener("tabkeydown", function(cmd, evt) {
+ var rng = me.selection.getRange();
+ var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);
+ if (pre) {
+ me.fireEvent("saveScene");
+ if (evt.shiftKey) {
+ } else {
+ if (!rng.collapsed) {
+ var bk = rng.createBookmark();
+ var start = bk.start.previousSibling;
+
+ while (start) {
+ if (pre.firstChild === start && !domUtils.isBr(start)) {
+ pre.insertBefore(me.document.createTextNode(" "), start);
+
+ break;
+ }
+ if (domUtils.isBr(start)) {
+ pre.insertBefore(
+ me.document.createTextNode(" "),
+ start.nextSibling
+ );
+
+ break;
+ }
+ start = start.previousSibling;
+ }
+ var end = bk.end;
+ start = bk.start.nextSibling;
+ if (pre.firstChild === bk.start) {
+ pre.insertBefore(
+ me.document.createTextNode(" "),
+ start.nextSibling
+ );
+ }
+ while (start && start !== end) {
+ if (domUtils.isBr(start) && start.nextSibling) {
+ if (start.nextSibling === end) {
+ break;
+ }
+ pre.insertBefore(
+ me.document.createTextNode(" "),
+ start.nextSibling
+ );
+ }
+
+ start = start.nextSibling;
+ }
+ rng.moveToBookmark(bk).select();
+ } else {
+ var tmpNode = me.document.createTextNode(" ");
+ rng
+ .insertNode(tmpNode)
+ .setStartAfter(tmpNode)
+ .collapse(true)
+ .select(true);
+ }
+ }
+
+ me.fireEvent("saveScene");
+ return true;
+ }
+ });
+
+ me.addListener("beforeinserthtml", function(evtName, html) {
+ var me = this,
+ rng = me.selection.getRange(),
+ pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);
+ if (pre) {
+ if (!rng.collapsed) {
+ rng.deleteContents();
+ }
+ var htmlstr = "";
+ if (browser.ie && browser.version > 8) {
+ utils.each(
+ UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules)
+ .children,
+ function(node) {
+ if (node.type == "element") {
+ if (node.tagName == "br") {
+ htmlstr += "\n";
+ } else if (!dtd.$empty[node.tagName]) {
+ utils.each(node.children, function(cn) {
+ if (cn.type == "element") {
+ if (cn.tagName == "br") {
+ htmlstr += "\n";
+ } else if (!dtd.$empty[node.tagName]) {
+ htmlstr += cn.innerText();
+ }
+ } else {
+ htmlstr += cn.data;
+ }
+ });
+ if (!/\n$/.test(htmlstr)) {
+ htmlstr += "\n";
+ }
+ }
+ } else {
+ htmlstr += node.data + "\n";
+ }
+ if (!node.nextSibling() && /\n$/.test(htmlstr)) {
+ htmlstr = htmlstr.replace(/\n$/, "");
+ }
+ }
+ );
+ var tmpNode = me.document.createTextNode(
+ utils.html(htmlstr.replace(/ /g, " "))
+ );
+ rng.insertNode(tmpNode).selectNode(tmpNode).select();
+ } else {
+ var frag = me.document.createDocumentFragment();
+
+ utils.each(
+ UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules)
+ .children,
+ function(node) {
+ if (node.type == "element") {
+ if (node.tagName == "br") {
+ frag.appendChild(me.document.createElement("br"));
+ } else if (!dtd.$empty[node.tagName]) {
+ utils.each(node.children, function(cn) {
+ if (cn.type == "element") {
+ if (cn.tagName == "br") {
+ frag.appendChild(me.document.createElement("br"));
+ } else if (!dtd.$empty[node.tagName]) {
+ frag.appendChild(
+ me.document.createTextNode(
+ utils.html(cn.innerText().replace(/ /g, " "))
+ )
+ );
+ }
+ } else {
+ frag.appendChild(
+ me.document.createTextNode(
+ utils.html(cn.data.replace(/ /g, " "))
+ )
+ );
+ }
+ });
+ if (frag.lastChild.nodeName != "BR") {
+ frag.appendChild(me.document.createElement("br"));
+ }
+ }
+ } else {
+ frag.appendChild(
+ me.document.createTextNode(
+ utils.html(node.data.replace(/ /g, " "))
+ )
+ );
+ }
+ if (!node.nextSibling() && frag.lastChild.nodeName == "BR") {
+ frag.removeChild(frag.lastChild);
+ }
+ }
+ );
+ rng.insertNode(frag).select();
+ }
+
+ return true;
+ }
+ });
+ //方向键的处理
+ me.addListener("keydown", function(cmd, evt) {
+ var me = this,
+ keyCode = evt.keyCode || evt.which;
+ if (keyCode == 40) {
+ var rng = me.selection.getRange(),
+ pre,
+ start = rng.startContainer;
+ if (
+ rng.collapsed &&
+ (pre = domUtils.findParentByTagName(rng.startContainer, "pre", true)) &&
+ !pre.nextSibling
+ ) {
+ var last = pre.lastChild;
+ while (last && last.nodeName == "BR") {
+ last = last.previousSibling;
+ }
+ if (
+ last === start ||
+ (rng.startContainer === pre &&
+ rng.startOffset == pre.childNodes.length)
+ ) {
+ me.execCommand("insertparagraph");
+ domUtils.preventDefault(evt);
+ }
+ }
+ }
+ });
+ //trace:3395
+ me.addListener("delkeydown", function(type, evt) {
+ var rng = this.selection.getRange();
+ rng.txtToElmBoundary(true);
+ var start = rng.startContainer;
+ if (
+ domUtils.isTagNode(start, "pre") &&
+ rng.collapsed &&
+ domUtils.isStartInblock(rng)
+ ) {
+ var p = me.document.createElement("p");
+ domUtils.fillNode(me.document, p);
+ start.parentNode.insertBefore(p, start);
+ domUtils.remove(start);
+ rng.setStart(p, 0).setCursor(false, true);
+ domUtils.preventDefault(evt);
+ return true;
+ }
+ });
+};
+
+
+// plugins/cleardoc.js
+/**
+ * 清空文档插件
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 清空文档
+ * @command cleardoc
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * //editor 是编辑器实例
+ * editor.execCommand('cleardoc');
+ * ```
+ */
+
+UE.commands["cleardoc"] = {
+ execCommand: function(cmdName) {
+ var me = this,
+ enterTag = me.options.enterTag,
+ range = me.selection.getRange();
+ if (enterTag == "br") {
+ me.body.innerHTML = " ";
+ range.setStart(me.body, 0).setCursor();
+ } else {
+ me.body.innerHTML = "" + (ie ? "" : " ") + " ";
+ range.setStart(me.body.firstChild, 0).setCursor(false, true);
+ }
+ setTimeout(function() {
+ me.fireEvent("clearDoc");
+ }, 0);
+ }
+};
+
+
+// plugins/anchor.js
+/**
+ * 锚点插件,为UEditor提供插入锚点支持
+ * @file
+ * @since 1.2.6.1
+ */
+UE.plugin.register("anchor", function () {
+ var me = this;
+ 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: 16px;}",
+ 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 = utils.renderTplstr(' ', {
+ name: name
+ });
+ me.execCommand("inserthtml", anchor, true);
+ }
+ }
+ }
+ }
+ }
+ };
+});
+
+
+// plugins/wordcount.js
+///import core
+///commands 字数统计
+///commandsName WordCount,wordCount
+///commandsTitle 字数统计
+/*
+ * Created by JetBrains WebStorm.
+ * User: taoqili
+ * Date: 11-9-7
+ * Time: 下午8:18
+ * To change this template use File | Settings | File Templates.
+ */
+
+UE.plugins["wordcount"] = function() {
+ var me = this;
+ me.setOpt("wordCount", true);
+ me.addListener("contentchange", function() {
+ me.fireEvent("wordcount");
+ });
+ var timer;
+ me.addListener("ready", function() {
+ var me = this;
+ domUtils.on(me.body, "keyup", function(evt) {
+ var code = evt.keyCode || evt.which,
+ //忽略的按键,ctr,alt,shift,方向键
+ ignores = {
+ "16": 1,
+ "18": 1,
+ "20": 1,
+ "37": 1,
+ "38": 1,
+ "39": 1,
+ "40": 1
+ };
+ if (code in ignores) return;
+ clearTimeout(timer);
+ timer = setTimeout(function() {
+ me.fireEvent("wordcount");
+ }, 200);
+ });
+ });
+};
+
+
+// plugins/pagebreak.js
+/**
+ * 分页功能插件
+ * @file
+ * @since 1.2.6.1
+ */
+UE.plugins["pagebreak"] = function() {
+ var me = this,
+ notBreakTags = ["td"];
+ me.setOpt("pageBreakTag", "_ueditor_page_break_tag_");
+
+ function fillNode(node) {
+ if (domUtils.isEmptyBlock(node)) {
+ var firstChild = node.firstChild,
+ tmpNode;
+
+ while (
+ firstChild &&
+ firstChild.nodeType == 1 &&
+ domUtils.isEmptyBlock(firstChild)
+ ) {
+ tmpNode = firstChild;
+ firstChild = firstChild.firstChild;
+ }
+ !tmpNode && (tmpNode = node);
+ domUtils.fillNode(me.document, tmpNode);
+ }
+ }
+ //分页符样式添加
+
+ me.ready(function() {
+ utils.cssRule(
+ "pagebreak",
+ ".pagebreak{display:block;clear:both !important;cursor:default !important;width: 100% !important;margin:0;}",
+ me.document
+ );
+ });
+ function isHr(node) {
+ return (
+ node &&
+ node.nodeType == 1 &&
+ node.tagName == "HR" &&
+ node.className == "pagebreak"
+ );
+ }
+ me.addInputRule(function(root) {
+ root.traversal(function(node) {
+ if (node.type == "text" && node.data == me.options.pageBreakTag) {
+ var hr = UE.uNode.createElement(
+ ' '
+ );
+ node.parentNode.insertBefore(hr, node);
+ node.parentNode.removeChild(node);
+ }
+ });
+ });
+ me.addOutputRule(function(node) {
+ utils.each(node.getNodesByTagName("hr"), function(n) {
+ if (n.getAttr("class") == "pagebreak") {
+ var txt = UE.uNode.createText(me.options.pageBreakTag);
+ n.parentNode.insertBefore(txt, n);
+ n.parentNode.removeChild(n);
+ }
+ });
+ });
+
+ /**
+ * 插入分页符
+ * @command pagebreak
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @remind 在表格中插入分页符会把表格切分成两部分
+ * @remind 获取编辑器内的数据时, 编辑器会把分页符转换成“_ueditor_page_break_tag_”字符串,
+ * 以便于提交数据到服务器端后处理分页。
+ * @example
+ * ```javascript
+ * editor.execCommand( 'pagebreak'); //插入一个hr标签,带有样式类名pagebreak
+ * ```
+ */
+
+ me.commands["pagebreak"] = {
+ execCommand: function() {
+ var range = me.selection.getRange(),
+ hr = me.document.createElement("hr");
+ domUtils.setAttributes(hr, {
+ class: "pagebreak",
+ noshade: "noshade",
+ size: "5"
+ });
+ domUtils.unSelectable(hr);
+ //table单独处理
+ var node = domUtils.findParentByTagName(
+ range.startContainer,
+ notBreakTags,
+ true
+ ),
+ parents = [],
+ pN;
+ if (node) {
+ switch (node.tagName) {
+ case "TD":
+ pN = node.parentNode;
+ if (!pN.previousSibling) {
+ var table = domUtils.findParentByTagName(pN, "table");
+ // var tableWrapDiv = table.parentNode;
+ // if(tableWrapDiv && tableWrapDiv.nodeType == 1
+ // && tableWrapDiv.tagName == 'DIV'
+ // && tableWrapDiv.getAttribute('dropdrag')
+ // ){
+ // domUtils.remove(tableWrapDiv,true);
+ // }
+ table.parentNode.insertBefore(hr, table);
+ parents = domUtils.findParents(hr, true);
+ } else {
+ pN.parentNode.insertBefore(hr, pN);
+ parents = domUtils.findParents(hr);
+ }
+ pN = parents[1];
+ if (hr !== pN) {
+ domUtils.breakParent(hr, pN);
+ }
+ //table要重写绑定一下拖拽
+ me.fireEvent("afteradjusttable", me.document);
+ }
+ } else {
+ if (!range.collapsed) {
+ range.deleteContents();
+ var start = range.startContainer;
+ while (
+ !domUtils.isBody(start) &&
+ domUtils.isBlockElm(start) &&
+ domUtils.isEmptyNode(start)
+ ) {
+ range.setStartBefore(start).collapse(true);
+ domUtils.remove(start);
+ start = range.startContainer;
+ }
+ }
+ range.insertNode(hr);
+
+ var pN = hr.parentNode,
+ nextNode;
+ while (!domUtils.isBody(pN)) {
+ domUtils.breakParent(hr, pN);
+ nextNode = hr.nextSibling;
+ if (nextNode && domUtils.isEmptyBlock(nextNode)) {
+ domUtils.remove(nextNode);
+ }
+ pN = hr.parentNode;
+ }
+ nextNode = hr.nextSibling;
+ var pre = hr.previousSibling;
+ if (isHr(pre)) {
+ domUtils.remove(pre);
+ } else {
+ pre && fillNode(pre);
+ }
+
+ if (!nextNode) {
+ var p = me.document.createElement("p");
+
+ hr.parentNode.appendChild(p);
+ domUtils.fillNode(me.document, p);
+ range.setStart(p, 0).collapse(true);
+ } else {
+ if (isHr(nextNode)) {
+ domUtils.remove(nextNode);
+ } else {
+ fillNode(nextNode);
+ }
+ range.setEndAfter(hr).collapse(false);
+ }
+
+ range.select(true);
+ }
+ }
+ };
+};
+
+
+// plugins/wordimage.js
+///import core
+///commands 本地图片引导上传
+///commandsName WordImage
+///commandsTitle 本地图片引导上传
+///commandsDialog dialogs\wordimage
+
+UE.plugin.register("wordimage", function() {
+ var me = this,
+ images = [];
+ return {
+ commands: {
+ wordimage: {
+ execCommand: function() {
+ var images = domUtils.getElementsByTagName(me.body, "img");
+ var urlList = [];
+ for (var i = 0, ci; (ci = images[i++]); ) {
+ var url = ci.getAttribute("word_img");
+ url && urlList.push(url);
+ }
+ return urlList;
+ },
+ queryCommandState: function() {
+ images = domUtils.getElementsByTagName(me.body, "img");
+ for (var i = 0, ci; (ci = images[i++]); ) {
+ if (ci.getAttribute("word_img")) {
+ return 1;
+ }
+ }
+ return -1;
+ },
+ notNeedUndo: true
+ }
+ },
+ inputRule: function(root) {
+ utils.each(root.getNodesByTagName("img"), function(img) {
+ var attrs = img.attrs,
+ flag = parseInt(attrs.width) < 128 || parseInt(attrs.height) < 43,
+ opt = me.options,
+ src = opt.UEDITOR_HOME_URL + "themes/notadd/images/spacer.gif";
+ if (attrs["src"] && /^(?:(file:\/+))/.test(attrs["src"])) {
+ img.setAttr({
+ width: attrs.width,
+ height: attrs.height,
+ alt: attrs.alt,
+ word_img: attrs.src,
+ src: src,
+ style:
+ "background:url(" +
+ (flag
+ ? opt.themePath + opt.theme + "/images/word.gif"
+ : opt.langPath + opt.lang + "/images/localimage.png") +
+ ") no-repeat center center;border:1px solid #ddd"
+ });
+ }
+ });
+ }
+ };
+});
+
+
+// plugins/dragdrop.js
+UE.plugins["dragdrop"] = function() {
+ var me = this;
+ me.ready(function() {
+ domUtils.on(this.body, "dragend", function() {
+ var rng = me.selection.getRange();
+ var node = rng.getClosedNode() || me.selection.getStart();
+
+ if (node && node.tagName == "IMG") {
+ var pre = node.previousSibling,
+ next;
+ while ((next = node.nextSibling)) {
+ if (
+ next.nodeType == 1 &&
+ next.tagName == "SPAN" &&
+ !next.firstChild
+ ) {
+ domUtils.remove(next);
+ } else {
+ break;
+ }
+ }
+
+ if (
+ ((pre && pre.nodeType == 1 && !domUtils.isEmptyBlock(pre)) || !pre) &&
+ (!next || (next && !domUtils.isEmptyBlock(next)))
+ ) {
+ if (pre && pre.tagName == "P" && !domUtils.isEmptyBlock(pre)) {
+ pre.appendChild(node);
+ domUtils.moveChild(next, pre);
+ domUtils.remove(next);
+ } else if (
+ next &&
+ next.tagName == "P" &&
+ !domUtils.isEmptyBlock(next)
+ ) {
+ next.insertBefore(node, next.firstChild);
+ }
+
+ if (pre && pre.tagName == "P" && domUtils.isEmptyBlock(pre)) {
+ domUtils.remove(pre);
+ }
+ if (next && next.tagName == "P" && domUtils.isEmptyBlock(next)) {
+ domUtils.remove(next);
+ }
+ rng.selectNode(node).select();
+ me.fireEvent("saveScene");
+ }
+ }
+ });
+ });
+ me.addListener("keyup", function(type, evt) {
+ var keyCode = evt.keyCode || evt.which;
+ if (keyCode == 13) {
+ var rng = me.selection.getRange(),
+ node;
+ if (
+ (node = domUtils.findParentByTagName(rng.startContainer, "p", true))
+ ) {
+ if (domUtils.getComputedStyle(node, "text-align") == "center") {
+ domUtils.removeStyle(node, "text-align");
+ }
+ }
+ }
+ });
+};
+
+
+// plugins/undo.js
+/**
+ * undo redo
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 撤销上一次执行的命令
+ * @command undo
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'undo' );
+ * ```
+ */
+
+/**
+ * 重做上一次执行的命令
+ * @command redo
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'redo' );
+ * ```
+ */
+
+UE.plugins["undo"] = function() {
+ var saveSceneTimer;
+ var me = this,
+ maxUndoCount = me.options.maxUndoCount || 20,
+ maxInputCount = me.options.maxInputCount || 20,
+ fillchar = new RegExp(domUtils.fillChar + "|", "gi"); // ie会产生多余的
+ var noNeedFillCharTags = {
+ ol: 1,
+ ul: 1,
+ table: 1,
+ tbody: 1,
+ tr: 1,
+ body: 1
+ };
+ var orgState = me.options.autoClearEmptyNode;
+ function compareAddr(indexA, indexB) {
+ if (indexA.length != indexB.length) return 0;
+ for (var i = 0, l = indexA.length; i < l; i++) {
+ if (indexA[i] != indexB[i]) return 0;
+ }
+ return 1;
+ }
+
+ function compareRangeAddress(rngAddrA, rngAddrB) {
+ if (rngAddrA.collapsed != rngAddrB.collapsed) {
+ return 0;
+ }
+ if (
+ !compareAddr(rngAddrA.startAddress, rngAddrB.startAddress) ||
+ !compareAddr(rngAddrA.endAddress, rngAddrB.endAddress)
+ ) {
+ return 0;
+ }
+ return 1;
+ }
+
+ function UndoManager() {
+ this.list = [];
+ this.index = 0;
+ this.hasUndo = false;
+ this.hasRedo = false;
+ this.undo = function() {
+ if (this.hasUndo) {
+ if (!this.list[this.index - 1] && this.list.length == 1) {
+ this.reset();
+ return;
+ }
+ while (
+ this.list[this.index].content == this.list[this.index - 1].content
+ ) {
+ this.index--;
+ if (this.index == 0) {
+ return this.restore(0);
+ }
+ }
+ this.restore(--this.index);
+ }
+ };
+ this.redo = function() {
+ if (this.hasRedo) {
+ while (
+ this.list[this.index].content == this.list[this.index + 1].content
+ ) {
+ this.index++;
+ if (this.index == this.list.length - 1) {
+ return this.restore(this.index);
+ }
+ }
+ this.restore(++this.index);
+ }
+ };
+
+ this.restore = function() {
+ var me = this.editor;
+ var scene = this.list[this.index];
+ var root = UE.htmlparser(scene.content.replace(fillchar, ""));
+ me.options.autoClearEmptyNode = false;
+ me.filterInputRule(root);
+ me.options.autoClearEmptyNode = orgState;
+ //trace:873
+ //去掉展位符
+ me.document.body.innerHTML = root.toHtml();
+ me.fireEvent("afterscencerestore");
+ //处理undo后空格不展位的问题
+ if (browser.ie) {
+ utils.each(
+ domUtils.getElementsByTagName(me.document, "td th caption p"),
+ function(node) {
+ if (domUtils.isEmptyNode(node)) {
+ domUtils.fillNode(me.document, node);
+ }
+ }
+ );
+ }
+
+ try {
+ var rng = new dom.Range(me.document).moveToAddress(scene.address);
+ rng.select(
+ noNeedFillCharTags[rng.startContainer.nodeName.toLowerCase()]
+ );
+ } catch (e) {}
+
+ this.update();
+ this.clearKey();
+ //不能把自己reset了
+ me.fireEvent("reset", true);
+ };
+
+ this.getScene = function() {
+ var me = this.editor;
+ var rng = me.selection.getRange(),
+ rngAddress = rng.createAddress(false, true);
+ me.fireEvent("beforegetscene");
+ var root = UE.htmlparser(me.body.innerHTML);
+ me.options.autoClearEmptyNode = false;
+ me.filterOutputRule(root);
+ me.options.autoClearEmptyNode = orgState;
+ var cont = root.toHtml();
+ //trace:3461
+ //这个会引起回退时导致空格丢失的情况
+ // browser.ie && (cont = cont.replace(/> <').replace(/\s*\s*/g, '>'));
+ me.fireEvent("aftergetscene");
+
+ return {
+ address: rngAddress,
+ content: cont
+ };
+ };
+ this.save = function(notCompareRange, notSetCursor) {
+ clearTimeout(saveSceneTimer);
+ var currentScene = this.getScene(notSetCursor),
+ lastScene = this.list[this.index];
+
+ if (lastScene && lastScene.content != currentScene.content) {
+ me.trigger("contentchange");
+ }
+ //内容相同位置相同不存
+ if (
+ lastScene &&
+ lastScene.content == currentScene.content &&
+ (notCompareRange
+ ? 1
+ : compareRangeAddress(lastScene.address, currentScene.address))
+ ) {
+ return;
+ }
+ this.list = this.list.slice(0, this.index + 1);
+ this.list.push(currentScene);
+ //如果大于最大数量了,就把最前的剔除
+ if (this.list.length > maxUndoCount) {
+ this.list.shift();
+ }
+ this.index = this.list.length - 1;
+ this.clearKey();
+ //跟新undo/redo状态
+ this.update();
+ };
+ this.update = function() {
+ this.hasRedo = !!this.list[this.index + 1];
+ this.hasUndo = !!this.list[this.index - 1];
+ };
+ this.reset = function() {
+ this.list = [];
+ this.index = 0;
+ this.hasUndo = false;
+ this.hasRedo = false;
+ this.clearKey();
+ };
+ this.clearKey = function() {
+ keycont = 0;
+ lastKeyCode = null;
+ };
+ }
+
+ me.undoManger = new UndoManager();
+ me.undoManger.editor = me;
+ function saveScene() {
+ this.undoManger.save();
+ }
+
+ me.addListener("saveScene", function() {
+ var args = Array.prototype.splice.call(arguments, 1);
+ this.undoManger.save.apply(this.undoManger, args);
+ });
+
+ // me.addListener('beforeexeccommand', saveScene);
+ // me.addListener('afterexeccommand', saveScene);
+
+ me.addListener("reset", function(type, exclude) {
+ if (!exclude) {
+ this.undoManger.reset();
+ }
+ });
+ me.commands["redo"] = me.commands["undo"] = {
+ execCommand: function(cmdName) {
+ this.undoManger[cmdName]();
+ },
+ queryCommandState: function(cmdName) {
+ return this.undoManger[
+ "has" + (cmdName.toLowerCase() == "undo" ? "Undo" : "Redo")
+ ]
+ ? 0
+ : -1;
+ },
+ notNeedUndo: 1
+ };
+
+ var keys = {
+ // /*Backspace*/ 8:1, /*Delete*/ 46:1,
+ /*Shift*/ 16: 1,
+ /*Ctrl*/ 17: 1,
+ /*Alt*/ 18: 1,
+ 37: 1,
+ 38: 1,
+ 39: 1,
+ 40: 1
+ },
+ keycont = 0,
+ lastKeyCode;
+ //输入法状态下不计算字符数
+ var inputType = false;
+ me.addListener("ready", function() {
+ domUtils.on(this.body, "compositionstart", function() {
+ inputType = true;
+ });
+ domUtils.on(this.body, "compositionend", function() {
+ inputType = false;
+ });
+ });
+ //快捷键
+ me.addshortcutkey({
+ Undo: "ctrl+90", //undo
+ Redo: "ctrl+89" //redo
+ });
+ var isCollapsed = true;
+ me.addListener("keydown", function(type, evt) {
+ var me = this;
+ var keyCode = evt.keyCode || evt.which;
+ if (
+ !keys[keyCode] &&
+ !evt.ctrlKey &&
+ !evt.metaKey &&
+ !evt.shiftKey &&
+ !evt.altKey
+ ) {
+ if (inputType) return;
+
+ if (!me.selection.getRange().collapsed) {
+ me.undoManger.save(false, true);
+ isCollapsed = false;
+ return;
+ }
+ if (me.undoManger.list.length == 0) {
+ me.undoManger.save(true);
+ }
+ clearTimeout(saveSceneTimer);
+ function save(cont) {
+ cont.undoManger.save(false, true);
+ cont.fireEvent("selectionchange");
+ }
+ saveSceneTimer = setTimeout(function() {
+ if (inputType) {
+ var interalTimer = setInterval(function() {
+ if (!inputType) {
+ save(me);
+ clearInterval(interalTimer);
+ }
+ }, 300);
+ return;
+ }
+ save(me);
+ }, 200);
+
+ lastKeyCode = keyCode;
+ keycont++;
+ if (keycont >= maxInputCount) {
+ save(me);
+ }
+ }
+ });
+ me.addListener("keyup", function(type, evt) {
+ var keyCode = evt.keyCode || evt.which;
+ if (
+ !keys[keyCode] &&
+ !evt.ctrlKey &&
+ !evt.metaKey &&
+ !evt.shiftKey &&
+ !evt.altKey
+ ) {
+ if (inputType) return;
+ if (!isCollapsed) {
+ this.undoManger.save(false, true);
+ isCollapsed = true;
+ }
+ }
+ });
+ //扩展实例,添加关闭和开启命令undo
+ me.stopCmdUndo = function() {
+ me.__hasEnterExecCommand = true;
+ };
+ me.startCmdUndo = function() {
+ me.__hasEnterExecCommand = false;
+ };
+};
+
+
+// plugins/copy.js
+UE.plugin.register("copy", function() {
+ var me = this;
+
+ function initZeroClipboard() {
+ ZeroClipboard.config({
+ debug: false,
+ swfPath:
+ me.options.UEDITOR_HOME_URL +
+ "third-party/zeroclipboard/ZeroClipboard.swf"
+ });
+
+ var client = (me.zeroclipboard = new ZeroClipboard());
+
+ // 复制内容
+ client.on("copy", function(e) {
+ var client = e.client,
+ rng = me.selection.getRange(),
+ div = document.createElement("div");
+
+ div.appendChild(rng.cloneContents());
+ client.setText(div.innerText || div.textContent);
+ client.setHtml(div.innerHTML);
+ rng.select();
+ });
+ // hover事件传递到target
+ client.on("mouseover mouseout", function(e) {
+ var target = e.target;
+ if (target) {
+ if (e.type == "mouseover") {
+ domUtils.addClass(target, "edui-state-hover");
+ } else if (e.type == "mouseout") {
+ domUtils.removeClasses(target, "edui-state-hover");
+ }
+ }
+ });
+ // flash加载不成功
+ client.on("wrongflash noflash", function() {
+ ZeroClipboard.destroy();
+ });
+
+ // 触发事件
+ me.fireEvent("zeroclipboardready", client);
+ }
+
+ return {
+ bindEvents: {
+ ready: function() {
+ if (!browser.ie) {
+ if (window.ZeroClipboard) {
+ initZeroClipboard();
+ } else {
+ utils.loadFile(
+ document,
+ {
+ src:
+ me.options.UEDITOR_HOME_URL +
+ "third-party/zeroclipboard/ZeroClipboard.js",
+ tag: "script",
+ type: "text/javascript",
+ defer: "defer"
+ },
+ function() {
+ initZeroClipboard();
+ }
+ );
+ }
+ }
+ }
+ },
+ commands: {
+ copy: {
+ execCommand: function(cmd) {
+ if (!me.document.execCommand("copy")) {
+ alert(me.getLang("copymsg"));
+ }
+ }
+ }
+ }
+ };
+});
+
+
+// plugins/paste.js
+///import core
+///import plugins/inserthtml.js
+///import plugins/undo.js
+///import plugins/serialize.js
+///commands 粘贴
+///commandsName PastePlain
+///commandsTitle 纯文本粘贴模式
+/**
+ * @description 粘贴
+ * @author zhanyi
+ */
+UE.plugins["paste"] = function() {
+ function getClipboardData(callback) {
+ var doc = this.document;
+ if (doc.getElementById("baidu_pastebin")) {
+ return;
+ }
+ var range = this.selection.getRange(),
+ bk = range.createBookmark(),
+ //创建剪贴的容器div
+ pastebin = doc.createElement("div");
+ pastebin.id = "baidu_pastebin";
+ // Safari 要求div必须有内容,才能粘贴内容进来
+ browser.webkit &&
+ pastebin.appendChild(
+ doc.createTextNode(domUtils.fillChar + domUtils.fillChar)
+ );
+ doc.body.appendChild(pastebin);
+ //trace:717 隐藏的span不能得到top
+ //bk.start.innerHTML = ' ';
+ bk.start.style.display = "";
+ pastebin.style.cssText =
+ "position:absolute;width:1px;height:1px;overflow:hidden;left:-1000px;white-space:nowrap;top:" +
+ //要在现在光标平行的位置加入,否则会出现跳动的问题
+ domUtils.getXY(bk.start).y +
+ "px";
+
+ range.selectNodeContents(pastebin).select(true);
+
+ setTimeout(function() {
+ if (browser.webkit) {
+ for (
+ var i = 0, pastebins = doc.querySelectorAll("#baidu_pastebin"), pi;
+ (pi = pastebins[i++]);
+
+ ) {
+ if (domUtils.isEmptyNode(pi)) {
+ domUtils.remove(pi);
+ } else {
+ pastebin = pi;
+ break;
+ }
+ }
+ }
+ try {
+ pastebin.parentNode.removeChild(pastebin);
+ } catch (e) {}
+ range.moveToBookmark(bk).select(true);
+ callback(pastebin);
+ }, 0);
+ }
+
+ var me = this;
+
+ me.setOpt({
+ retainOnlyLabelPasted: false
+ });
+
+ var txtContent, htmlContent, address;
+
+ function getPureHtml(html) {
+ return html.replace(/<(\/?)([\w\-]+)([^>]*)>/gi, function(
+ a,
+ b,
+ tagName,
+ attrs
+ ) {
+ tagName = tagName.toLowerCase();
+ if ({ img: 1 }[tagName]) {
+ return a;
+ }
+ attrs = attrs.replace(
+ /([\w\-]*?)\s*=\s*(("([^"]*)")|('([^']*)')|([^\s>]+))/gi,
+ function(str, atr, val) {
+ if (
+ {
+ src: 1,
+ href: 1,
+ name: 1
+ }[atr.toLowerCase()]
+ ) {
+ return atr + "=" + val + " ";
+ }
+ return "";
+ }
+ );
+ if (
+ {
+ span: 1,
+ div: 1
+ }[tagName]
+ ) {
+ return "";
+ } else {
+ return "<" + b + tagName + " " + utils.trim(attrs) + ">";
+ }
+ });
+ }
+ function filter(div) {
+ var html;
+ if (div.firstChild) {
+ //去掉cut中添加的边界值
+ var nodes = domUtils.getElementsByTagName(div, "span");
+ for (var i = 0, ni; (ni = nodes[i++]); ) {
+ if (ni.id == "_baidu_cut_start" || ni.id == "_baidu_cut_end") {
+ domUtils.remove(ni);
+ }
+ }
+
+ if (browser.webkit) {
+ var brs = div.querySelectorAll("div br");
+ for (var i = 0, bi; (bi = brs[i++]); ) {
+ var pN = bi.parentNode;
+ if (pN.tagName == "DIV" && pN.childNodes.length == 1) {
+ pN.innerHTML = "
";
+ domUtils.remove(pN);
+ }
+ }
+ var divs = div.querySelectorAll("#baidu_pastebin");
+ for (var i = 0, di; (di = divs[i++]); ) {
+ var tmpP = me.document.createElement("p");
+ di.parentNode.insertBefore(tmpP, di);
+ while (di.firstChild) {
+ tmpP.appendChild(di.firstChild);
+ }
+ domUtils.remove(di);
+ }
+
+ var metas = div.querySelectorAll("meta");
+ for (var i = 0, ci; (ci = metas[i++]); ) {
+ domUtils.remove(ci);
+ }
+
+ var brs = div.querySelectorAll("br");
+ for (i = 0; (ci = brs[i++]); ) {
+ if (/^apple-/i.test(ci.className)) {
+ domUtils.remove(ci);
+ }
+ }
+ }
+ if (browser.gecko) {
+ var dirtyNodes = div.querySelectorAll("[_moz_dirty]");
+ for (i = 0; (ci = dirtyNodes[i++]); ) {
+ ci.removeAttribute("_moz_dirty");
+ }
+ }
+ if (!browser.ie) {
+ var spans = div.querySelectorAll("span.Apple-style-span");
+ for (var i = 0, ci; (ci = spans[i++]); ) {
+ domUtils.remove(ci, true);
+ }
+ }
+
+ //ie下使用innerHTML会产生多余的\r\n字符,也会产生 这里过滤掉
+ html = div.innerHTML; //.replace(/>(?:(\s| )*?)<');
+
+ //过滤word粘贴过来的冗余属性
+ html = UE.filterWord(html);
+ //取消了忽略空白的第二个参数,粘贴过来的有些是有空白的,会被套上相关的标签
+ var root = UE.htmlparser(html);
+ //如果给了过滤规则就先进行过滤
+ if (me.options.filterRules) {
+ UE.filterNode(root, me.options.filterRules);
+ }
+ //执行默认的处理
+ me.filterInputRule(root);
+ //针对chrome的处理
+ if (browser.webkit) {
+ var br = root.lastChild();
+ if (br && br.type == "element" && br.tagName == "br") {
+ root.removeChild(br);
+ }
+ utils.each(me.body.querySelectorAll("div"), function(node) {
+ if (domUtils.isEmptyBlock(node)) {
+ domUtils.remove(node, true);
+ }
+ });
+ }
+ html = { html: root.toHtml() };
+ me.fireEvent("beforepaste", html, root);
+ //抢了默认的粘贴,那后边的内容就不执行了,比如表格粘贴
+ if (!html.html) {
+ return;
+ }
+ root = UE.htmlparser(html.html, true);
+ //如果开启了纯文本模式
+ if (me.queryCommandState("pasteplain") === 1) {
+ me.execCommand(
+ "insertHtml",
+ UE.filterNode(root, me.options.filterTxtRules).toHtml(),
+ true
+ );
+ } else {
+ //文本模式
+ UE.filterNode(root, me.options.filterTxtRules);
+ txtContent = root.toHtml();
+ //完全模式
+ htmlContent = html.html;
+
+ address = me.selection.getRange().createAddress(true);
+ me.execCommand(
+ "insertHtml",
+ me.getOpt("retainOnlyLabelPasted") === true
+ ? getPureHtml(htmlContent)
+ : htmlContent,
+ true
+ );
+ }
+ me.fireEvent("afterpaste", html);
+ }
+ }
+
+ me.addListener("pasteTransfer", function(cmd, plainType) {
+ if (address && txtContent && htmlContent && txtContent != htmlContent) {
+ var range = me.selection.getRange();
+ range.moveToAddress(address, true);
+
+ if (!range.collapsed) {
+ while (!domUtils.isBody(range.startContainer)) {
+ var start = range.startContainer;
+ if (start.nodeType == 1) {
+ start = start.childNodes[range.startOffset];
+ if (!start) {
+ range.setStartBefore(range.startContainer);
+ continue;
+ }
+ var pre = start.previousSibling;
+
+ if (
+ pre &&
+ pre.nodeType == 3 &&
+ new RegExp("^[\n\r\t " + domUtils.fillChar + "]*$").test(
+ pre.nodeValue
+ )
+ ) {
+ range.setStartBefore(pre);
+ }
+ }
+ if (range.startOffset == 0) {
+ range.setStartBefore(range.startContainer);
+ } else {
+ break;
+ }
+ }
+ while (!domUtils.isBody(range.endContainer)) {
+ var end = range.endContainer;
+ if (end.nodeType == 1) {
+ end = end.childNodes[range.endOffset];
+ if (!end) {
+ range.setEndAfter(range.endContainer);
+ continue;
+ }
+ var next = end.nextSibling;
+ if (
+ next &&
+ next.nodeType == 3 &&
+ new RegExp("^[\n\r\t" + domUtils.fillChar + "]*$").test(
+ next.nodeValue
+ )
+ ) {
+ range.setEndAfter(next);
+ }
+ }
+ if (
+ range.endOffset ==
+ range.endContainer[
+ range.endContainer.nodeType == 3 ? "nodeValue" : "childNodes"
+ ].length
+ ) {
+ range.setEndAfter(range.endContainer);
+ } else {
+ break;
+ }
+ }
+ }
+
+ range.deleteContents();
+ range.select(true);
+ me.__hasEnterExecCommand = true;
+ var html = htmlContent;
+ if (plainType === 2) {
+ html = getPureHtml(html);
+ } else if (plainType) {
+ html = txtContent;
+ }
+ me.execCommand("inserthtml", html, true);
+ me.__hasEnterExecCommand = false;
+ var rng = me.selection.getRange();
+ while (
+ !domUtils.isBody(rng.startContainer) &&
+ !rng.startOffset &&
+ rng.startContainer[
+ rng.startContainer.nodeType == 3 ? "nodeValue" : "childNodes"
+ ].length
+ ) {
+ rng.setStartBefore(rng.startContainer);
+ }
+ var tmpAddress = rng.createAddress(true);
+ address.endAddress = tmpAddress.startAddress;
+ }
+ });
+
+ me.addListener("ready", function() {
+ domUtils.on(me.body, "cut", function() {
+ var range = me.selection.getRange();
+ if (!range.collapsed && me.undoManger) {
+ if (me.undoManger.list.length < 1) me.undoManger.save();
+ setTimeout(function() {
+ me.undoManger.save();
+ });
+ }
+ });
+
+ //ie下beforepaste在点击右键时也会触发,所以用监控键盘才处理
+ domUtils.on(
+ me.body,
+ browser.ie || browser.opera ? "keydown" : "paste",
+ function(e) {
+ if (
+ (browser.ie || browser.opera) &&
+ ((!e.ctrlKey && !e.metaKey) || e.keyCode != "86")
+ ) {
+ return;
+ }
+ getClipboardData.call(me, function(div) {
+ filter(div);
+ });
+ }
+ );
+ });
+
+ me.commands["paste"] = {
+ execCommand: function(cmd) {
+ if (browser.ie) {
+ getClipboardData.call(me, function(div) {
+ filter(div);
+ });
+ me.document.execCommand("paste");
+ } else {
+ alert(me.getLang("pastemsg"));
+ }
+ }
+ };
+};
+
+
+// plugins/puretxtpaste.js
+/**
+ * 纯文本粘贴插件
+ * @file
+ * @since 1.2.6.1
+ */
+
+UE.plugins["pasteplain"] = function() {
+ var me = this;
+ me.setOpt({
+ pasteplain: false,
+ filterTxtRules: (function() {
+ function transP(node) {
+ node.tagName = "p";
+ node.setStyle();
+ }
+ function removeNode(node) {
+ node.parentNode.removeChild(node, true);
+ }
+ return {
+ //直接删除及其字节点内容
+ "-": "script style object iframe embed input select",
+ p: { $: {} },
+ br: { $: {} },
+ div: function(node) {
+ var tmpNode,
+ p = UE.uNode.createElement("p");
+ while ((tmpNode = node.firstChild())) {
+ if (tmpNode.type == "text" || !UE.dom.dtd.$block[tmpNode.tagName]) {
+ p.appendChild(tmpNode);
+ } else {
+ if (p.firstChild()) {
+ node.parentNode.insertBefore(p, node);
+ p = UE.uNode.createElement("p");
+ } else {
+ node.parentNode.insertBefore(tmpNode, node);
+ }
+ }
+ }
+ if (p.firstChild()) {
+ node.parentNode.insertBefore(p, node);
+ }
+ node.parentNode.removeChild(node);
+ },
+ ol: removeNode,
+ ul: removeNode,
+ dl: removeNode,
+ dt: removeNode,
+ dd: removeNode,
+ li: removeNode,
+ caption: transP,
+ th: transP,
+ tr: transP,
+ h1: transP,
+ h2: transP,
+ h3: transP,
+ h4: transP,
+ h5: transP,
+ h6: transP,
+ td: function(node) {
+ //没有内容的td直接删掉
+ var txt = !!node.innerText();
+ if (txt) {
+ node.parentNode.insertAfter(
+ UE.uNode.createText(" "),
+ node
+ );
+ }
+ node.parentNode.removeChild(node, node.innerText());
+ }
+ };
+ })()
+ });
+ //暂时这里支持一下老版本的属性
+ var pasteplain = me.options.pasteplain;
+
+ /**
+ * 启用或取消纯文本粘贴模式
+ * @command pasteplain
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.queryCommandState( 'pasteplain' );
+ * ```
+ */
+
+ /**
+ * 查询当前是否处于纯文本粘贴模式
+ * @command pasteplain
+ * @method queryCommandState
+ * @param { String } cmd 命令字符串
+ * @return { int } 如果处于纯文本模式,返回1,否则,返回0
+ * @example
+ * ```javascript
+ * editor.queryCommandState( 'pasteplain' );
+ * ```
+ */
+ me.commands["pasteplain"] = {
+ queryCommandState: function() {
+ return pasteplain ? 1 : 0;
+ },
+ execCommand: function() {
+ pasteplain = !pasteplain | 0;
+ },
+ notNeedUndo: 1
+ };
+};
+
+
+// plugins/list.js
+/**
+ * 有序列表,无序列表插件
+ * @file
+ * @since 1.2.6.1
+ */
+
+UE.plugins["list"] = function() {
+ var me = this,
+ notExchange = {
+ TD: 1,
+ PRE: 1,
+ BLOCKQUOTE: 1
+ };
+ var customStyle = {
+ cn: "cn-1-",
+ cn1: "cn-2-",
+ cn2: "cn-3-",
+ num: "num-1-",
+ num1: "num-2-",
+ num2: "num-3-",
+ dash: "dash",
+ dot: "dot"
+ };
+
+ me.setOpt({
+ autoTransWordToList: false,
+ insertorderedlist: {
+ num: "",
+ num1: "",
+ num2: "",
+ cn: "",
+ cn1: "",
+ cn2: "",
+ decimal: "",
+ "lower-alpha": "",
+ "lower-roman": "",
+ "upper-alpha": "",
+ "upper-roman": ""
+ },
+ insertunorderedlist: {
+ circle: "",
+ disc: "",
+ square: "",
+ dash: "",
+ dot: ""
+ },
+ listDefaultPaddingLeft: "30",
+ listiconpath: "http://bs.baidu.com/listicon/",
+ maxListLevel: -1, //-1不限制
+ disablePInList: false
+ });
+ function listToArray(list) {
+ var arr = [];
+ for (var p in list) {
+ arr.push(p);
+ }
+ return arr;
+ }
+ var listStyle = {
+ OL: listToArray(me.options.insertorderedlist),
+ UL: listToArray(me.options.insertunorderedlist)
+ };
+ var liiconpath = me.options.listiconpath;
+
+ //根据用户配置,调整customStyle
+ for (var s in customStyle) {
+ if (
+ !me.options.insertorderedlist.hasOwnProperty(s) &&
+ !me.options.insertunorderedlist.hasOwnProperty(s)
+ ) {
+ delete customStyle[s];
+ }
+ }
+
+ me.ready(function() {
+ var customCss = [];
+ for (var p in customStyle) {
+ if (p == "dash" || p == "dot") {
+ customCss.push(
+ "li.list-" +
+ customStyle[p] +
+ "{background-image:url(" +
+ liiconpath +
+ customStyle[p] +
+ ".gif)}"
+ );
+ customCss.push(
+ "ul.custom_" +
+ p +
+ "{list-style:none;}ul.custom_" +
+ p +
+ " li{background-position:0 3px;background-repeat:no-repeat}"
+ );
+ } else {
+ for (var i = 0; i < 99; i++) {
+ customCss.push(
+ "li.list-" +
+ customStyle[p] +
+ i +
+ "{background-image:url(" +
+ liiconpath +
+ "list-" +
+ customStyle[p] +
+ i +
+ ".gif)}"
+ );
+ }
+ customCss.push(
+ "ol.custom_" +
+ p +
+ "{list-style:none;}ol.custom_" +
+ p +
+ " li{background-position:0 3px;background-repeat:no-repeat}"
+ );
+ }
+ switch (p) {
+ case "cn":
+ customCss.push("li.list-" + p + "-paddingleft-1{padding-left:25px}");
+ customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}");
+ customCss.push("li.list-" + p + "-paddingleft-3{padding-left:55px}");
+ break;
+ case "cn1":
+ customCss.push("li.list-" + p + "-paddingleft-1{padding-left:30px}");
+ customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}");
+ customCss.push("li.list-" + p + "-paddingleft-3{padding-left:55px}");
+ break;
+ case "cn2":
+ customCss.push("li.list-" + p + "-paddingleft-1{padding-left:40px}");
+ customCss.push("li.list-" + p + "-paddingleft-2{padding-left:55px}");
+ customCss.push("li.list-" + p + "-paddingleft-3{padding-left:68px}");
+ break;
+ case "num":
+ case "num1":
+ customCss.push("li.list-" + p + "-paddingleft-1{padding-left:25px}");
+ break;
+ case "num2":
+ customCss.push("li.list-" + p + "-paddingleft-1{padding-left:35px}");
+ customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}");
+ break;
+ case "dash":
+ customCss.push("li.list-" + p + "-paddingleft{padding-left:35px}");
+ break;
+ case "dot":
+ customCss.push("li.list-" + p + "-paddingleft{padding-left:20px}");
+ }
+ }
+ customCss.push(".list-paddingleft-1{padding-left:0}");
+ customCss.push(
+ ".list-paddingleft-2{padding-left:" +
+ me.options.listDefaultPaddingLeft +
+ "px}"
+ );
+ customCss.push(
+ ".list-paddingleft-3{padding-left:" +
+ me.options.listDefaultPaddingLeft * 2 +
+ "px}"
+ );
+ //如果不给宽度会在自定应样式里出现滚动条
+ utils.cssRule(
+ "list",
+ "ol,ul{margin:0;pading:0;" +
+ (browser.ie ? "" : "width:95%") +
+ "}li{clear:both;}" +
+ customCss.join("\n"),
+ me.document
+ );
+ });
+ //单独处理剪切的问题
+ me.ready(function() {
+ domUtils.on(me.body, "cut", function() {
+ setTimeout(function() {
+ var rng = me.selection.getRange(),
+ li;
+ //trace:3416
+ if (!rng.collapsed) {
+ if (
+ (li = domUtils.findParentByTagName(rng.startContainer, "li", true))
+ ) {
+ if (!li.nextSibling && domUtils.isEmptyBlock(li)) {
+ var pn = li.parentNode,
+ node;
+ if ((node = pn.previousSibling)) {
+ domUtils.remove(pn);
+ rng.setStartAtLast(node).collapse(true);
+ rng.select(true);
+ } else if ((node = pn.nextSibling)) {
+ domUtils.remove(pn);
+ rng.setStartAtFirst(node).collapse(true);
+ rng.select(true);
+ } else {
+ var tmpNode = me.document.createElement("p");
+ domUtils.fillNode(me.document, tmpNode);
+ pn.parentNode.insertBefore(tmpNode, pn);
+ domUtils.remove(pn);
+ rng.setStart(tmpNode, 0).collapse(true);
+ rng.select(true);
+ }
+ }
+ }
+ }
+ });
+ });
+ });
+
+ function getStyle(node) {
+ var cls = node.className;
+ if (domUtils.hasClass(node, /custom_/)) {
+ return cls.match(/custom_(\w+)/)[1];
+ }
+ return domUtils.getStyle(node, "list-style-type");
+ }
+
+ me.addListener("beforepaste", function(type, html) {
+ var me = this,
+ rng = me.selection.getRange(),
+ li;
+ var root = UE.htmlparser(html.html, true);
+ if ((li = domUtils.findParentByTagName(rng.startContainer, "li", true))) {
+ var list = li.parentNode,
+ tagName = list.tagName == "OL" ? "ul" : "ol";
+ utils.each(root.getNodesByTagName(tagName), function(n) {
+ n.tagName = list.tagName;
+ n.setAttr();
+ if (n.parentNode === root) {
+ type = getStyle(list) || (list.tagName == "OL" ? "decimal" : "disc");
+ } else {
+ var className = n.parentNode.getAttr("class");
+ if (className && /custom_/.test(className)) {
+ type = className.match(/custom_(\w+)/)[1];
+ } else {
+ type = n.parentNode.getStyle("list-style-type");
+ }
+ if (!type) {
+ type = list.tagName == "OL" ? "decimal" : "disc";
+ }
+ }
+ var index = utils.indexOf(listStyle[list.tagName], type);
+ if (n.parentNode !== root)
+ index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
+ var currentStyle = listStyle[list.tagName][index];
+ if (customStyle[currentStyle]) {
+ n.setAttr("class", "custom_" + currentStyle);
+ } else {
+ n.setStyle("list-style-type", currentStyle);
+ }
+ });
+ }
+
+ html.html = root.toHtml();
+ });
+ //导出时,去掉p标签
+ me.getOpt("disablePInList") === true &&
+ me.addOutputRule(function(root) {
+ utils.each(root.getNodesByTagName("li"), function(li) {
+ var newChildrens = [],
+ index = 0;
+ utils.each(li.children, function(n) {
+ if (n.tagName == "p") {
+ var tmpNode;
+ while ((tmpNode = n.children.pop())) {
+ newChildrens.splice(index, 0, tmpNode);
+ tmpNode.parentNode = li;
+ lastNode = tmpNode;
+ }
+ tmpNode = newChildrens[newChildrens.length - 1];
+ if (
+ !tmpNode ||
+ tmpNode.type != "element" ||
+ tmpNode.tagName != "br"
+ ) {
+ var br = UE.uNode.createElement("br");
+ br.parentNode = li;
+ newChildrens.push(br);
+ }
+
+ index = newChildrens.length;
+ }
+ });
+ if (newChildrens.length) {
+ li.children = newChildrens;
+ }
+ });
+ });
+ //进入编辑器的li要套p标签
+ me.addInputRule(function(root) {
+ utils.each(root.getNodesByTagName("li"), function(li) {
+ var tmpP = UE.uNode.createElement("p");
+ for (var i = 0, ci; (ci = li.children[i]); ) {
+ if (ci.type == "text" || dtd.p[ci.tagName]) {
+ tmpP.appendChild(ci);
+ } else {
+ if (tmpP.firstChild()) {
+ li.insertBefore(tmpP, ci);
+ tmpP = UE.uNode.createElement("p");
+ i = i + 2;
+ } else {
+ i++;
+ }
+ }
+ }
+ if ((tmpP.firstChild() && !tmpP.parentNode) || !li.firstChild()) {
+ li.appendChild(tmpP);
+ }
+ //trace:3357
+ //p不能为空
+ if (!tmpP.firstChild()) {
+ tmpP.innerHTML(browser.ie ? " " : " ");
+ }
+ //去掉末尾的空白
+ var p = li.firstChild();
+ var lastChild = p.lastChild();
+ if (
+ lastChild &&
+ lastChild.type == "text" &&
+ /^\s*$/.test(lastChild.data)
+ ) {
+ p.removeChild(lastChild);
+ }
+ });
+ if (me.options.autoTransWordToList) {
+ var orderlisttype = {
+ num1: /^\d+\)/,
+ decimal: /^\d+\./,
+ "lower-alpha": /^[a-z]+\)/,
+ "upper-alpha": /^[A-Z]+\./,
+ cn: /^[\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+[\u3001]/,
+ cn2: /^\([\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+\)/
+ },
+ unorderlisttype = {
+ square: "n"
+ };
+ function checkListType(content, container) {
+ var span = container.firstChild();
+ if (
+ span &&
+ span.type == "element" &&
+ span.tagName == "span" &&
+ /Wingdings|Symbol/.test(span.getStyle("font-family"))
+ ) {
+ for (var p in unorderlisttype) {
+ if (unorderlisttype[p] == span.data) {
+ return p;
+ }
+ }
+ return "disc";
+ }
+ for (var p in orderlisttype) {
+ if (orderlisttype[p].test(content)) {
+ return p;
+ }
+ }
+ }
+ utils.each(root.getNodesByTagName("p"), function(node) {
+ if (node.getAttr("class") != "MsoListParagraph") {
+ return;
+ }
+
+ //word粘贴过来的会带有margin要去掉,但这样也可能会误命中一些央视
+ node.setStyle("margin", "");
+ node.setStyle("margin-left", "");
+ node.setAttr("class", "");
+
+ function appendLi(list, p, type) {
+ if (list.tagName == "ol") {
+ if (browser.ie) {
+ var first = p.firstChild();
+ if (
+ first.type == "element" &&
+ first.tagName == "span" &&
+ orderlisttype[type].test(first.innerText())
+ ) {
+ p.removeChild(first);
+ }
+ } else {
+ p.innerHTML(p.innerHTML().replace(orderlisttype[type], ""));
+ }
+ } else {
+ p.removeChild(p.firstChild());
+ }
+
+ var li = UE.uNode.createElement("li");
+ li.appendChild(p);
+ list.appendChild(li);
+ }
+ var tmp = node,
+ type,
+ cacheNode = node;
+
+ if (
+ node.parentNode.tagName != "li" &&
+ (type = checkListType(node.innerText(), node))
+ ) {
+ var list = UE.uNode.createElement(
+ me.options.insertorderedlist.hasOwnProperty(type) ? "ol" : "ul"
+ );
+ if (customStyle[type]) {
+ list.setAttr("class", "custom_" + type);
+ } else {
+ list.setStyle("list-style-type", type);
+ }
+ while (
+ node &&
+ node.parentNode.tagName != "li" &&
+ checkListType(node.innerText(), node)
+ ) {
+ tmp = node.nextSibling();
+ if (!tmp) {
+ node.parentNode.insertBefore(list, node);
+ }
+ appendLi(list, node, type);
+ node = tmp;
+ }
+ if (!list.parentNode && node && node.parentNode) {
+ node.parentNode.insertBefore(list, node);
+ }
+ }
+ var span = cacheNode.firstChild();
+ if (
+ span &&
+ span.type == "element" &&
+ span.tagName == "span" &&
+ /^\s*( )+\s*$/.test(span.innerText())
+ ) {
+ span.parentNode.removeChild(span);
+ }
+ });
+ }
+ });
+
+ //调整索引标签
+ me.addListener("contentchange", function() {
+ adjustListStyle(me.document);
+ });
+
+ function adjustListStyle(doc, ignore) {
+ utils.each(domUtils.getElementsByTagName(doc, "ol ul"), function(node) {
+ if (!domUtils.inDoc(node, doc)) return;
+
+ var parent = node.parentNode;
+ if (parent.tagName == node.tagName) {
+ var nodeStyleType =
+ getStyle(node) || (node.tagName == "OL" ? "decimal" : "disc"),
+ parentStyleType =
+ getStyle(parent) || (parent.tagName == "OL" ? "decimal" : "disc");
+ if (nodeStyleType == parentStyleType) {
+ var styleIndex = utils.indexOf(
+ listStyle[node.tagName],
+ nodeStyleType
+ );
+ styleIndex = styleIndex + 1 == listStyle[node.tagName].length
+ ? 0
+ : styleIndex + 1;
+ setListStyle(node, listStyle[node.tagName][styleIndex]);
+ }
+ }
+ var index = 0,
+ type = 2;
+ if (domUtils.hasClass(node, /custom_/)) {
+ if (
+ !(
+ /[ou]l/i.test(parent.tagName) &&
+ domUtils.hasClass(parent, /custom_/)
+ )
+ ) {
+ type = 1;
+ }
+ } else {
+ if (
+ /[ou]l/i.test(parent.tagName) &&
+ domUtils.hasClass(parent, /custom_/)
+ ) {
+ type = 3;
+ }
+ }
+
+ var style = domUtils.getStyle(node, "list-style-type");
+ style && (node.style.cssText = "list-style-type:" + style);
+ node.className =
+ utils.trim(node.className.replace(/list-paddingleft-\w+/, "")) +
+ " list-paddingleft-" +
+ type;
+ utils.each(domUtils.getElementsByTagName(node, "li"), function(li) {
+ li.style.cssText && (li.style.cssText = "");
+ if (!li.firstChild) {
+ domUtils.remove(li);
+ return;
+ }
+ if (li.parentNode !== node) {
+ return;
+ }
+ index++;
+ if (domUtils.hasClass(node, /custom_/)) {
+ var paddingLeft = 1,
+ currentStyle = getStyle(node);
+ if (node.tagName == "OL") {
+ if (currentStyle) {
+ switch (currentStyle) {
+ case "cn":
+ case "cn1":
+ case "cn2":
+ if (
+ index > 10 &&
+ (index % 10 == 0 || (index > 10 && index < 20))
+ ) {
+ paddingLeft = 2;
+ } else if (index > 20) {
+ paddingLeft = 3;
+ }
+ break;
+ case "num2":
+ if (index > 9) {
+ paddingLeft = 2;
+ }
+ }
+ }
+ li.className =
+ "list-" +
+ customStyle[currentStyle] +
+ index +
+ " " +
+ "list-" +
+ currentStyle +
+ "-paddingleft-" +
+ paddingLeft;
+ } else {
+ li.className =
+ "list-" +
+ customStyle[currentStyle] +
+ " " +
+ "list-" +
+ currentStyle +
+ "-paddingleft";
+ }
+ } else {
+ li.className = li.className.replace(/list-[\w\-]+/gi, "");
+ }
+ var className = li.getAttribute("class");
+ if (className !== null && !className.replace(/\s/g, "")) {
+ domUtils.removeAttributes(li, "class");
+ }
+ });
+ !ignore &&
+ adjustList(
+ node,
+ node.tagName.toLowerCase(),
+ getStyle(node) || domUtils.getStyle(node, "list-style-type"),
+ true
+ );
+ });
+ }
+ function adjustList(list, tag, style, ignoreEmpty) {
+ var nextList = list.nextSibling;
+ if (
+ nextList &&
+ nextList.nodeType == 1 &&
+ nextList.tagName.toLowerCase() == tag &&
+ (getStyle(nextList) ||
+ domUtils.getStyle(nextList, "list-style-type") ||
+ (tag == "ol" ? "decimal" : "disc")) == style
+ ) {
+ domUtils.moveChild(nextList, list);
+ if (nextList.childNodes.length == 0) {
+ domUtils.remove(nextList);
+ }
+ }
+ if (nextList && domUtils.isFillChar(nextList)) {
+ domUtils.remove(nextList);
+ }
+ var preList = list.previousSibling;
+ if (
+ preList &&
+ preList.nodeType == 1 &&
+ preList.tagName.toLowerCase() == tag &&
+ (getStyle(preList) ||
+ domUtils.getStyle(preList, "list-style-type") ||
+ (tag == "ol" ? "decimal" : "disc")) == style
+ ) {
+ domUtils.moveChild(list, preList);
+ }
+ if (preList && domUtils.isFillChar(preList)) {
+ domUtils.remove(preList);
+ }
+ !ignoreEmpty && domUtils.isEmptyBlock(list) && domUtils.remove(list);
+ if (getStyle(list)) {
+ adjustListStyle(list.ownerDocument, true);
+ }
+ }
+
+ function setListStyle(list, style) {
+ if (customStyle[style]) {
+ list.className = "custom_" + style;
+ }
+ try {
+ domUtils.setStyle(list, "list-style-type", style);
+ } catch (e) {}
+ }
+ function clearEmptySibling(node) {
+ var tmpNode = node.previousSibling;
+ if (tmpNode && domUtils.isEmptyBlock(tmpNode)) {
+ domUtils.remove(tmpNode);
+ }
+ tmpNode = node.nextSibling;
+ if (tmpNode && domUtils.isEmptyBlock(tmpNode)) {
+ domUtils.remove(tmpNode);
+ }
+ }
+
+ me.addListener("keydown", function(type, evt) {
+ function preventAndSave() {
+ evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
+ me.fireEvent("contentchange");
+ me.undoManger && me.undoManger.save();
+ }
+ function findList(node, filterFn) {
+ while (node && !domUtils.isBody(node)) {
+ if (filterFn(node)) {
+ return null;
+ }
+ if (node.nodeType == 1 && /[ou]l/i.test(node.tagName)) {
+ return node;
+ }
+ node = node.parentNode;
+ }
+ return null;
+ }
+ var keyCode = evt.keyCode || evt.which;
+ if (keyCode == 13 && !evt.shiftKey) {
+ //回车
+ var rng = me.selection.getRange(),
+ parent = domUtils.findParent(
+ rng.startContainer,
+ function(node) {
+ return domUtils.isBlockElm(node);
+ },
+ true
+ ),
+ li = domUtils.findParentByTagName(rng.startContainer, "li", true);
+ if (parent && parent.tagName != "PRE" && !li) {
+ var html = parent.innerHTML.replace(
+ new RegExp(domUtils.fillChar, "g"),
+ ""
+ );
+ if (/^\s*1\s*\.[^\d]/.test(html)) {
+ parent.innerHTML = html.replace(/^\s*1\s*\./, "");
+ rng.setStartAtLast(parent).collapse(true).select();
+ me.__hasEnterExecCommand = true;
+ me.execCommand("insertorderedlist");
+ me.__hasEnterExecCommand = false;
+ }
+ }
+ var range = me.selection.getRange(),
+ start = findList(range.startContainer, function(node) {
+ return node.tagName == "TABLE";
+ }),
+ end = range.collapsed
+ ? start
+ : findList(range.endContainer, function(node) {
+ return node.tagName == "TABLE";
+ });
+
+ if (start && end && start === end) {
+ if (!range.collapsed) {
+ start = domUtils.findParentByTagName(
+ range.startContainer,
+ "li",
+ true
+ );
+ end = domUtils.findParentByTagName(range.endContainer, "li", true);
+ if (start && end && start === end) {
+ range.deleteContents();
+ li = domUtils.findParentByTagName(range.startContainer, "li", true);
+ if (li && domUtils.isEmptyBlock(li)) {
+ pre = li.previousSibling;
+ next = li.nextSibling;
+ p = me.document.createElement("p");
+
+ domUtils.fillNode(me.document, p);
+ parentList = li.parentNode;
+ if (pre && next) {
+ range.setStart(next, 0).collapse(true).select(true);
+ domUtils.remove(li);
+ } else {
+ if ((!pre && !next) || !pre) {
+ parentList.parentNode.insertBefore(p, parentList);
+ } else {
+ li.parentNode.parentNode.insertBefore(
+ p,
+ parentList.nextSibling
+ );
+ }
+ domUtils.remove(li);
+ if (!parentList.firstChild) {
+ domUtils.remove(parentList);
+ }
+ range.setStart(p, 0).setCursor();
+ }
+ preventAndSave();
+ return;
+ }
+ } else {
+ var tmpRange = range.cloneRange(),
+ bk = tmpRange.collapse(false).createBookmark();
+
+ range.deleteContents();
+ tmpRange.moveToBookmark(bk);
+ var li = domUtils.findParentByTagName(
+ tmpRange.startContainer,
+ "li",
+ true
+ );
+
+ clearEmptySibling(li);
+ tmpRange.select();
+ preventAndSave();
+ return;
+ }
+ }
+
+ li = domUtils.findParentByTagName(range.startContainer, "li", true);
+
+ if (li) {
+ if (domUtils.isEmptyBlock(li)) {
+ bk = range.createBookmark();
+ var parentList = li.parentNode;
+ if (li !== parentList.lastChild) {
+ domUtils.breakParent(li, parentList);
+ clearEmptySibling(li);
+ } else {
+ parentList.parentNode.insertBefore(li, parentList.nextSibling);
+ if (domUtils.isEmptyNode(parentList)) {
+ domUtils.remove(parentList);
+ }
+ }
+ //嵌套不处理
+ if (!dtd.$list[li.parentNode.tagName]) {
+ if (!domUtils.isBlockElm(li.firstChild)) {
+ p = me.document.createElement("p");
+ li.parentNode.insertBefore(p, li);
+ while (li.firstChild) {
+ p.appendChild(li.firstChild);
+ }
+ domUtils.remove(li);
+ } else {
+ domUtils.remove(li, true);
+ }
+ }
+ range.moveToBookmark(bk).select();
+ } else {
+ var first = li.firstChild;
+ if (!first || !domUtils.isBlockElm(first)) {
+ var p = me.document.createElement("p");
+
+ !li.firstChild && domUtils.fillNode(me.document, p);
+ while (li.firstChild) {
+ p.appendChild(li.firstChild);
+ }
+ li.appendChild(p);
+ first = p;
+ }
+
+ var span = me.document.createElement("span");
+
+ range.insertNode(span);
+ domUtils.breakParent(span, li);
+
+ var nextLi = span.nextSibling;
+ first = nextLi.firstChild;
+
+ if (!first) {
+ p = me.document.createElement("p");
+
+ domUtils.fillNode(me.document, p);
+ nextLi.appendChild(p);
+ first = p;
+ }
+ if (domUtils.isEmptyNode(first)) {
+ first.innerHTML = "";
+ domUtils.fillNode(me.document, first);
+ }
+
+ range.setStart(first, 0).collapse(true).shrinkBoundary().select();
+ domUtils.remove(span);
+ var pre = nextLi.previousSibling;
+ if (pre && domUtils.isEmptyBlock(pre)) {
+ pre.innerHTML = "";
+ domUtils.fillNode(me.document, pre.firstChild);
+ }
+ }
+ // }
+ preventAndSave();
+ }
+ }
+ }
+ if (keyCode == 8) {
+ //修中ie中li下的问题
+ range = me.selection.getRange();
+ if (range.collapsed && domUtils.isStartInblock(range)) {
+ tmpRange = range.cloneRange().trimBoundary();
+ li = domUtils.findParentByTagName(range.startContainer, "li", true);
+ //要在li的最左边,才能处理
+ if (li && domUtils.isStartInblock(tmpRange)) {
+ start = domUtils.findParentByTagName(range.startContainer, "p", true);
+ if (start && start !== li.firstChild) {
+ var parentList = domUtils.findParentByTagName(start, ["ol", "ul"]);
+ domUtils.breakParent(start, parentList);
+ clearEmptySibling(start);
+ me.fireEvent("contentchange");
+ range.setStart(start, 0).setCursor(false, true);
+ me.fireEvent("saveScene");
+ domUtils.preventDefault(evt);
+ return;
+ }
+
+ if (li && (pre = li.previousSibling)) {
+ if (keyCode == 46 && li.childNodes.length) {
+ return;
+ }
+ //有可能上边的兄弟节点是个2级菜单,要追加到2级菜单的最后的li
+ if (dtd.$list[pre.tagName]) {
+ pre = pre.lastChild;
+ }
+ me.undoManger && me.undoManger.save();
+ first = li.firstChild;
+ if (domUtils.isBlockElm(first)) {
+ if (domUtils.isEmptyNode(first)) {
+ // range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true);
+ pre.appendChild(first);
+ range.setStart(first, 0).setCursor(false, true);
+ //first不是唯一的节点
+ while (li.firstChild) {
+ pre.appendChild(li.firstChild);
+ }
+ } else {
+ span = me.document.createElement("span");
+ range.insertNode(span);
+ //判断pre是否是空的节点,如果是
类型的空节点,干掉p标签防止它占位
+ if (domUtils.isEmptyBlock(pre)) {
+ pre.innerHTML = "";
+ }
+ domUtils.moveChild(li, pre);
+ range.setStartBefore(span).collapse(true).select(true);
+
+ domUtils.remove(span);
+ }
+ } else {
+ if (domUtils.isEmptyNode(li)) {
+ var p = me.document.createElement("p");
+ pre.appendChild(p);
+ range.setStart(p, 0).setCursor();
+ // range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true);
+ } else {
+ range
+ .setEnd(pre, pre.childNodes.length)
+ .collapse()
+ .select(true);
+ while (li.firstChild) {
+ pre.appendChild(li.firstChild);
+ }
+ }
+ }
+ domUtils.remove(li);
+ me.fireEvent("contentchange");
+ me.fireEvent("saveScene");
+ domUtils.preventDefault(evt);
+ return;
+ }
+ //trace:980
+
+ if (li && !li.previousSibling) {
+ var parentList = li.parentNode;
+ var bk = range.createBookmark();
+ if (domUtils.isTagNode(parentList.parentNode, "ol ul")) {
+ parentList.parentNode.insertBefore(li, parentList);
+ if (domUtils.isEmptyNode(parentList)) {
+ domUtils.remove(parentList);
+ }
+ } else {
+ while (li.firstChild) {
+ parentList.parentNode.insertBefore(li.firstChild, parentList);
+ }
+
+ domUtils.remove(li);
+ if (domUtils.isEmptyNode(parentList)) {
+ domUtils.remove(parentList);
+ }
+ }
+ range.moveToBookmark(bk).setCursor(false, true);
+ me.fireEvent("contentchange");
+ me.fireEvent("saveScene");
+ domUtils.preventDefault(evt);
+ return;
+ }
+ }
+ }
+ }
+ });
+
+ me.addListener("keyup", function(type, evt) {
+ var keyCode = evt.keyCode || evt.which;
+ if (keyCode == 8) {
+ var rng = me.selection.getRange(),
+ list;
+ if (
+ (list = domUtils.findParentByTagName(
+ rng.startContainer,
+ ["ol", "ul"],
+ true
+ ))
+ ) {
+ adjustList(
+ list,
+ list.tagName.toLowerCase(),
+ getStyle(list) || domUtils.getComputedStyle(list, "list-style-type"),
+ true
+ );
+ }
+ }
+ });
+ //处理tab键
+ me.addListener("tabkeydown", function() {
+ var range = me.selection.getRange();
+
+ //控制级数
+ function checkLevel(li) {
+ if (me.options.maxListLevel != -1) {
+ var level = li.parentNode,
+ levelNum = 0;
+ while (/[ou]l/i.test(level.tagName)) {
+ levelNum++;
+ level = level.parentNode;
+ }
+ if (levelNum >= me.options.maxListLevel) {
+ return true;
+ }
+ }
+ }
+ //只以开始为准
+ //todo 后续改进
+ var li = domUtils.findParentByTagName(range.startContainer, "li", true);
+ if (li) {
+ var bk;
+ if (range.collapsed) {
+ if (checkLevel(li)) return true;
+ var parentLi = li.parentNode,
+ list = me.document.createElement(parentLi.tagName),
+ index = utils.indexOf(
+ listStyle[list.tagName],
+ getStyle(parentLi) ||
+ domUtils.getComputedStyle(parentLi, "list-style-type")
+ );
+ index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
+ var currentStyle = listStyle[list.tagName][index];
+ setListStyle(list, currentStyle);
+ if (domUtils.isStartInblock(range)) {
+ me.fireEvent("saveScene");
+ bk = range.createBookmark();
+ parentLi.insertBefore(list, li);
+ list.appendChild(li);
+ adjustList(list, list.tagName.toLowerCase(), currentStyle);
+ me.fireEvent("contentchange");
+ range.moveToBookmark(bk).select(true);
+ return true;
+ }
+ } else {
+ me.fireEvent("saveScene");
+ bk = range.createBookmark();
+ for (
+ var i = 0, closeList, parents = domUtils.findParents(li), ci;
+ (ci = parents[i++]);
+
+ ) {
+ if (domUtils.isTagNode(ci, "ol ul")) {
+ closeList = ci;
+ break;
+ }
+ }
+ var current = li;
+ if (bk.end) {
+ while (
+ current &&
+ !(
+ domUtils.getPosition(current, bk.end) &
+ domUtils.POSITION_FOLLOWING
+ )
+ ) {
+ if (checkLevel(current)) {
+ current = domUtils.getNextDomNode(current, false, null, function(
+ node
+ ) {
+ return node !== closeList;
+ });
+ continue;
+ }
+ var parentLi = current.parentNode,
+ list = me.document.createElement(parentLi.tagName),
+ index = utils.indexOf(
+ listStyle[list.tagName],
+ getStyle(parentLi) ||
+ domUtils.getComputedStyle(parentLi, "list-style-type")
+ );
+ var currentIndex = index + 1 == listStyle[list.tagName].length
+ ? 0
+ : index + 1;
+ var currentStyle = listStyle[list.tagName][currentIndex];
+ setListStyle(list, currentStyle);
+ parentLi.insertBefore(list, current);
+ while (
+ current &&
+ !(
+ domUtils.getPosition(current, bk.end) &
+ domUtils.POSITION_FOLLOWING
+ )
+ ) {
+ li = current.nextSibling;
+ list.appendChild(current);
+ if (!li || domUtils.isTagNode(li, "ol ul")) {
+ if (li) {
+ while ((li = li.firstChild)) {
+ if (li.tagName == "LI") {
+ break;
+ }
+ }
+ } else {
+ li = domUtils.getNextDomNode(current, false, null, function(
+ node
+ ) {
+ return node !== closeList;
+ });
+ }
+ break;
+ }
+ current = li;
+ }
+ adjustList(list, list.tagName.toLowerCase(), currentStyle);
+ current = li;
+ }
+ }
+ me.fireEvent("contentchange");
+ range.moveToBookmark(bk).select();
+ return true;
+ }
+ }
+ });
+ function getLi(start) {
+ while (start && !domUtils.isBody(start)) {
+ if (start.nodeName == "TABLE") {
+ return null;
+ }
+ if (start.nodeName == "LI") {
+ return start;
+ }
+ start = start.parentNode;
+ }
+ }
+
+ /**
+ * 有序列表,与“insertunorderedlist”命令互斥
+ * @command insertorderedlist
+ * @method execCommand
+ * @param { String } command 命令字符串
+ * @param { String } style 插入的有序列表类型,值为:decimal,lower-alpha,lower-roman,upper-alpha,upper-roman,cn,cn1,cn2,num,num1,num2
+ * @example
+ * ```javascript
+ * editor.execCommand( 'insertorderedlist','decimal');
+ * ```
+ */
+ /**
+ * 查询当前选区内容是否有序列表
+ * @command insertorderedlist
+ * @method queryCommandState
+ * @param { String } cmd 命令字符串
+ * @return { int } 如果当前选区是有序列表返回1,否则返回0
+ * @example
+ * ```javascript
+ * editor.queryCommandState( 'insertorderedlist' );
+ * ```
+ */
+ /**
+ * 查询当前选区内容是否有序列表
+ * @command insertorderedlist
+ * @method queryCommandValue
+ * @param { String } cmd 命令字符串
+ * @return { String } 返回当前有序列表的类型,值为null或decimal,lower-alpha,lower-roman,upper-alpha,upper-roman,cn,cn1,cn2,num,num1,num2
+ * @example
+ * ```javascript
+ * editor.queryCommandValue( 'insertorderedlist' );
+ * ```
+ */
+
+ /**
+ * 无序列表,与“insertorderedlist”命令互斥
+ * @command insertunorderedlist
+ * @method execCommand
+ * @param { String } command 命令字符串
+ * @param { String } style 插入的无序列表类型,值为:circle,disc,square,dash,dot
+ * @example
+ * ```javascript
+ * editor.execCommand( 'insertunorderedlist','circle');
+ * ```
+ */
+ /**
+ * 查询当前是否有word文档粘贴进来的图片
+ * @command insertunorderedlist
+ * @method insertunorderedlist
+ * @param { String } command 命令字符串
+ * @return { int } 如果当前选区是无序列表返回1,否则返回0
+ * @example
+ * ```javascript
+ * editor.queryCommandState( 'insertunorderedlist' );
+ * ```
+ */
+ /**
+ * 查询当前选区内容是否有序列表
+ * @command insertunorderedlist
+ * @method queryCommandValue
+ * @param { String } command 命令字符串
+ * @return { String } 返回当前无序列表的类型,值为null或circle,disc,square,dash,dot
+ * @example
+ * ```javascript
+ * editor.queryCommandValue( 'insertunorderedlist' );
+ * ```
+ */
+
+ me.commands["insertorderedlist"] = me.commands["insertunorderedlist"] = {
+ execCommand: function(command, style) {
+ if (!style) {
+ style = command.toLowerCase() == "insertorderedlist"
+ ? "decimal"
+ : "disc";
+ }
+ var me = this,
+ range = this.selection.getRange(),
+ filterFn = function(node) {
+ return node.nodeType == 1
+ ? node.tagName.toLowerCase() != "br"
+ : !domUtils.isWhitespace(node);
+ },
+ tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul",
+ frag = me.document.createDocumentFragment();
+ //去掉是因为会出现选到末尾,导致adjustmentBoundary缩到ol/ul的位置
+ //range.shrinkBoundary();//.adjustmentBoundary();
+ range.adjustmentBoundary().shrinkBoundary();
+ var bko = range.createBookmark(true),
+ start = getLi(me.document.getElementById(bko.start)),
+ modifyStart = 0,
+ end = getLi(me.document.getElementById(bko.end)),
+ modifyEnd = 0,
+ startParent,
+ endParent,
+ list,
+ tmp;
+
+ if (start || end) {
+ start && (startParent = start.parentNode);
+ if (!bko.end) {
+ end = start;
+ }
+ end && (endParent = end.parentNode);
+
+ if (startParent === endParent) {
+ while (start !== end) {
+ tmp = start;
+ start = start.nextSibling;
+ if (!domUtils.isBlockElm(tmp.firstChild)) {
+ var p = me.document.createElement("p");
+ while (tmp.firstChild) {
+ p.appendChild(tmp.firstChild);
+ }
+ tmp.appendChild(p);
+ }
+ frag.appendChild(tmp);
+ }
+ tmp = me.document.createElement("span");
+ startParent.insertBefore(tmp, end);
+ if (!domUtils.isBlockElm(end.firstChild)) {
+ p = me.document.createElement("p");
+ while (end.firstChild) {
+ p.appendChild(end.firstChild);
+ }
+ end.appendChild(p);
+ }
+ frag.appendChild(end);
+ domUtils.breakParent(tmp, startParent);
+ if (domUtils.isEmptyNode(tmp.previousSibling)) {
+ domUtils.remove(tmp.previousSibling);
+ }
+ if (domUtils.isEmptyNode(tmp.nextSibling)) {
+ domUtils.remove(tmp.nextSibling);
+ }
+ var nodeStyle =
+ getStyle(startParent) ||
+ domUtils.getComputedStyle(startParent, "list-style-type") ||
+ (command.toLowerCase() == "insertorderedlist" ? "decimal" : "disc");
+ if (startParent.tagName.toLowerCase() == tag && nodeStyle == style) {
+ for (
+ var i = 0, ci, tmpFrag = me.document.createDocumentFragment();
+ (ci = frag.firstChild);
+
+ ) {
+ if (domUtils.isTagNode(ci, "ol ul")) {
+ // 删除时,子列表不处理
+ // utils.each(domUtils.getElementsByTagName(ci,'li'),function(li){
+ // while(li.firstChild){
+ // tmpFrag.appendChild(li.firstChild);
+ // }
+ //
+ // });
+ tmpFrag.appendChild(ci);
+ } else {
+ while (ci.firstChild) {
+ tmpFrag.appendChild(ci.firstChild);
+ domUtils.remove(ci);
+ }
+ }
+ }
+ tmp.parentNode.insertBefore(tmpFrag, tmp);
+ } else {
+ list = me.document.createElement(tag);
+ setListStyle(list, style);
+ list.appendChild(frag);
+ tmp.parentNode.insertBefore(list, tmp);
+ }
+
+ domUtils.remove(tmp);
+ list && adjustList(list, tag, style);
+ range.moveToBookmark(bko).select();
+ return;
+ }
+ //开始
+ if (start) {
+ while (start) {
+ tmp = start.nextSibling;
+ if (domUtils.isTagNode(start, "ol ul")) {
+ frag.appendChild(start);
+ } else {
+ var tmpfrag = me.document.createDocumentFragment(),
+ hasBlock = 0;
+ while (start.firstChild) {
+ if (domUtils.isBlockElm(start.firstChild)) {
+ hasBlock = 1;
+ }
+ tmpfrag.appendChild(start.firstChild);
+ }
+ if (!hasBlock) {
+ var tmpP = me.document.createElement("p");
+ tmpP.appendChild(tmpfrag);
+ frag.appendChild(tmpP);
+ } else {
+ frag.appendChild(tmpfrag);
+ }
+ domUtils.remove(start);
+ }
+
+ start = tmp;
+ }
+ startParent.parentNode.insertBefore(frag, startParent.nextSibling);
+ if (domUtils.isEmptyNode(startParent)) {
+ range.setStartBefore(startParent);
+ domUtils.remove(startParent);
+ } else {
+ range.setStartAfter(startParent);
+ }
+ modifyStart = 1;
+ }
+
+ if (end && domUtils.inDoc(endParent, me.document)) {
+ //结束
+ start = endParent.firstChild;
+ while (start && start !== end) {
+ tmp = start.nextSibling;
+ if (domUtils.isTagNode(start, "ol ul")) {
+ frag.appendChild(start);
+ } else {
+ tmpfrag = me.document.createDocumentFragment();
+ hasBlock = 0;
+ while (start.firstChild) {
+ if (domUtils.isBlockElm(start.firstChild)) {
+ hasBlock = 1;
+ }
+ tmpfrag.appendChild(start.firstChild);
+ }
+ if (!hasBlock) {
+ tmpP = me.document.createElement("p");
+ tmpP.appendChild(tmpfrag);
+ frag.appendChild(tmpP);
+ } else {
+ frag.appendChild(tmpfrag);
+ }
+ domUtils.remove(start);
+ }
+ start = tmp;
+ }
+ var tmpDiv = domUtils.createElement(me.document, "div", {
+ tmpDiv: 1
+ });
+ domUtils.moveChild(end, tmpDiv);
+
+ frag.appendChild(tmpDiv);
+ domUtils.remove(end);
+ endParent.parentNode.insertBefore(frag, endParent);
+ range.setEndBefore(endParent);
+ if (domUtils.isEmptyNode(endParent)) {
+ domUtils.remove(endParent);
+ }
+
+ modifyEnd = 1;
+ }
+ }
+
+ if (!modifyStart) {
+ range.setStartBefore(me.document.getElementById(bko.start));
+ }
+ if (bko.end && !modifyEnd) {
+ range.setEndAfter(me.document.getElementById(bko.end));
+ }
+ range.enlarge(true, function(node) {
+ return notExchange[node.tagName];
+ });
+
+ frag = me.document.createDocumentFragment();
+
+ var bk = range.createBookmark(),
+ current = domUtils.getNextDomNode(bk.start, false, filterFn),
+ tmpRange = range.cloneRange(),
+ tmpNode,
+ block = domUtils.isBlockElm;
+
+ while (
+ current &&
+ current !== bk.end &&
+ domUtils.getPosition(current, bk.end) & domUtils.POSITION_PRECEDING
+ ) {
+ if (current.nodeType == 3 || dtd.li[current.tagName]) {
+ if (current.nodeType == 1 && dtd.$list[current.tagName]) {
+ while (current.firstChild) {
+ frag.appendChild(current.firstChild);
+ }
+ tmpNode = domUtils.getNextDomNode(current, false, filterFn);
+ domUtils.remove(current);
+ current = tmpNode;
+ continue;
+ }
+ tmpNode = current;
+ tmpRange.setStartBefore(current);
+
+ while (
+ current &&
+ current !== bk.end &&
+ (!block(current) || domUtils.isBookmarkNode(current))
+ ) {
+ tmpNode = current;
+ current = domUtils.getNextDomNode(current, false, null, function(
+ node
+ ) {
+ return !notExchange[node.tagName];
+ });
+ }
+
+ if (current && block(current)) {
+ tmp = domUtils.getNextDomNode(tmpNode, false, filterFn);
+ if (tmp && domUtils.isBookmarkNode(tmp)) {
+ current = domUtils.getNextDomNode(tmp, false, filterFn);
+ tmpNode = tmp;
+ }
+ }
+ tmpRange.setEndAfter(tmpNode);
+
+ current = domUtils.getNextDomNode(tmpNode, false, filterFn);
+
+ var li = range.document.createElement("li");
+
+ li.appendChild(tmpRange.extractContents());
+ if (domUtils.isEmptyNode(li)) {
+ var tmpNode = range.document.createElement("p");
+ while (li.firstChild) {
+ tmpNode.appendChild(li.firstChild);
+ }
+ li.appendChild(tmpNode);
+ }
+ frag.appendChild(li);
+ } else {
+ current = domUtils.getNextDomNode(current, true, filterFn);
+ }
+ }
+ range.moveToBookmark(bk).collapse(true);
+ list = me.document.createElement(tag);
+ setListStyle(list, style);
+ list.appendChild(frag);
+ range.insertNode(list);
+ //当前list上下看能否合并
+ adjustList(list, tag, style);
+ //去掉冗余的tmpDiv
+ for (
+ var i = 0, ci, tmpDivs = domUtils.getElementsByTagName(list, "div");
+ (ci = tmpDivs[i++]);
+
+ ) {
+ if (ci.getAttribute("tmpDiv")) {
+ domUtils.remove(ci, true);
+ }
+ }
+ range.moveToBookmark(bko).select();
+ },
+ queryCommandState: function(command) {
+ var tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul";
+ var path = this.selection.getStartElementPath();
+ for (var i = 0, ci; (ci = path[i++]); ) {
+ if (ci.nodeName == "TABLE") {
+ return 0;
+ }
+ if (tag == ci.nodeName.toLowerCase()) {
+ return 1;
+ }
+ }
+ return 0;
+ },
+ queryCommandValue: function(command) {
+ var tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul";
+ var path = this.selection.getStartElementPath(),
+ node;
+ for (var i = 0, ci; (ci = path[i++]); ) {
+ if (ci.nodeName == "TABLE") {
+ node = null;
+ break;
+ }
+ if (tag == ci.nodeName.toLowerCase()) {
+ node = ci;
+ break;
+ }
+ }
+ return node
+ ? getStyle(node) || domUtils.getComputedStyle(node, "list-style-type")
+ : null;
+ }
+ };
+};
+
+
+// plugins/source.js
+/**
+ * 源码编辑插件
+ * @file
+ * @since 1.2.6.1
+ */
+
+;(function() {
+ var sourceEditors = {
+ textarea: function(editor, holder) {
+ var textarea = holder.ownerDocument.createElement("textarea");
+ textarea.style.cssText =
+ "position:absolute;resize:none;width:100%;height:100%;border:0;padding:0;margin:0;overflow-y:auto;";
+ // todo: IE下只有onresize属性可用... 很纠结
+ if (browser.ie && browser.version < 8) {
+ textarea.style.width = holder.offsetWidth + "px";
+ textarea.style.height = holder.offsetHeight + "px";
+ holder.onresize = function() {
+ textarea.style.width = holder.offsetWidth + "px";
+ textarea.style.height = holder.offsetHeight + "px";
+ };
+ }
+ holder.appendChild(textarea);
+ return {
+ setContent: function(content) {
+ textarea.value = content;
+ },
+ getContent: function() {
+ return textarea.value;
+ },
+ select: function() {
+ var range;
+ if (browser.ie) {
+ range = textarea.createTextRange();
+ range.collapse(true);
+ range.select();
+ } else {
+ //todo: chrome下无法设置焦点
+ textarea.setSelectionRange(0, 0);
+ textarea.focus();
+ }
+ },
+ dispose: function() {
+ holder.removeChild(textarea);
+ // todo
+ holder.onresize = null;
+ textarea = null;
+ holder = null;
+ },
+ 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]
+ if (rng.endContainer && rng.endContainer.nodeType == 1) {
+ tmpNode = rng.endContainer.childNodes[rng.endOffset];
+ if (tmpNode && domUtils.isBr(tmpNode)) {
+ rng.setEndAfter(tmpNode);
+ }
+ }
+ if (rng.startOffset == 0) {
+ tmpNode = rng.startContainer;
+ if (domUtils.isBoundaryNode(tmpNode, "firstChild")) {
+ tmpNode = rng.endContainer;
+ if (
+ rng.endOffset ==
+ (tmpNode.nodeType == 3
+ ? tmpNode.nodeValue.length
+ : tmpNode.childNodes.length) &&
+ domUtils.isBoundaryNode(tmpNode, "lastChild")
+ ) {
+ me.fireEvent("saveScene");
+ me.body.innerHTML = " " + (browser.ie ? "" : " ") + " ";
+ rng.setStart(me.body.firstChild, 0).setCursor(false, true);
+ me._selectionChange();
+ return;
+ }
+ }
+ }
+ }
+
+ //处理backspace
+ if (keyCode == keymap.Backspace) {
+ rng = me.selection.getRange();
+ collapsed = rng.collapsed;
+ if (me.fireEvent("delkeydown", evt)) {
+ return;
+ }
+ var start, end;
+ //避免按两次删除才能生效的问题
+ if (rng.collapsed && rng.inFillChar()) {
+ start = rng.startContainer;
+
+ if (domUtils.isFillChar(start)) {
+ rng.setStartBefore(start).shrinkBoundary(true).collapse(true);
+ domUtils.remove(start);
+ } else {
+ start.nodeValue = start.nodeValue.replace(
+ new RegExp("^" + domUtils.fillChar),
+ ""
+ );
+ rng.startOffset--;
+ rng.collapse(true).select(true);
+ }
+ }
+
+ //解决选中control元素不能删除的问题
+ if ((start = rng.getClosedNode())) {
+ me.fireEvent("saveScene");
+ rng.setStartBefore(start);
+ domUtils.remove(start);
+ rng.setCursor();
+ me.fireEvent("saveScene");
+ domUtils.preventDefault(evt);
+ return;
+ }
+ //阻止在table上的删除
+ if (!browser.ie) {
+ start = domUtils.findParentByTagName(rng.startContainer, "table", true);
+ end = domUtils.findParentByTagName(rng.endContainer, "table", true);
+ if ((start && !end) || (!start && end) || start !== end) {
+ evt.preventDefault();
+ return;
+ }
+ }
+ }
+ //处理tab键的逻辑
+ if (keyCode == keymap.Tab) {
+ //不处理以下标签
+ var excludeTagNameForTabKey = {
+ ol: 1,
+ ul: 1,
+ table: 1
+ };
+ //处理组件里的tab按下事件
+ if (me.fireEvent("tabkeydown", evt)) {
+ domUtils.preventDefault(evt);
+ return;
+ }
+ var range = me.selection.getRange();
+ me.fireEvent("saveScene");
+ for (
+ var i = 0,
+ txt = "",
+ tabSize = me.options.tabSize || 4,
+ tabNode = me.options.tabNode || " ";
+ i < tabSize;
+ i++
+ ) {
+ txt += tabNode;
+ }
+ var span = me.document.createElement("span");
+ span.innerHTML = txt + domUtils.fillChar;
+ if (range.collapsed) {
+ range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
+ } else {
+ var filterFn = function(node) {
+ return (
+ domUtils.isBlockElm(node) &&
+ !excludeTagNameForTabKey[node.tagName.toLowerCase()]
+ );
+ };
+ //普通的情况
+ start = domUtils.findParent(range.startContainer, filterFn, true);
+ end = domUtils.findParent(range.endContainer, filterFn, true);
+ if (start && end && start === end) {
+ range.deleteContents();
+ range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
+ } else {
+ var bookmark = range.createBookmark();
+ range.enlarge(true);
+ var bookmark2 = range.createBookmark(),
+ current = domUtils.getNextDomNode(bookmark2.start, false, filterFn);
+ while (
+ current &&
+ !(
+ domUtils.getPosition(current, bookmark2.end) &
+ domUtils.POSITION_FOLLOWING
+ )
+ ) {
+ current.insertBefore(
+ span.cloneNode(true).firstChild,
+ current.firstChild
+ );
+ current = domUtils.getNextDomNode(current, false, filterFn);
+ }
+ range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select();
+ }
+ }
+ domUtils.preventDefault(evt);
+ }
+ //trace:1634
+ //ff的del键在容器空的时候,也会删除
+ if (browser.gecko && keyCode == 46) {
+ range = me.selection.getRange();
+ if (range.collapsed) {
+ start = range.startContainer;
+ if (domUtils.isEmptyBlock(start)) {
+ var parent = start.parentNode;
+ while (
+ domUtils.getChildCount(parent) == 1 &&
+ !domUtils.isBody(parent)
+ ) {
+ start = parent;
+ parent = parent.parentNode;
+ }
+ if (start === parent.lastChild) evt.preventDefault();
+ return;
+ }
+ }
+ }
+
+ /* 修复在编辑区域快捷键 (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 : " "
+ });
+ rng.insertNode(tmpNode).setStart(tmpNode, 0).setCursor(false, true);
+ }
+ }
+
+ //chrome下如果删除了inline标签,浏览器会有记忆,在输入文字还是会套上刚才删除的标签,所以这里再选一次就不会了
+ if (
+ !collapsed &&
+ (rng.startContainer.nodeType == 3 ||
+ (rng.startContainer.nodeType == 1 &&
+ domUtils.isEmptyBlock(rng.startContainer)))
+ ) {
+ if (browser.ie) {
+ var span = rng.document.createElement("span");
+ rng.insertNode(span).setStartBefore(span).collapse(true);
+ rng.select();
+ domUtils.remove(span);
+ } else {
+ rng.select();
+ }
+ }
+ }
+ });
+};
+
+
+// plugins/fiximgclick.js
+///import core
+///commands 修复chrome下图片不能点击的问题,出现八个角可改变大小
+///commandsName FixImgClick
+///commandsTitle 修复chrome下图片不能点击的问题,出现八个角可改变大小
+//修复chrome下图片不能点击的问题,出现八个角可改变大小
+
+UE.plugins["fiximgclick"] = (function() {
+ var elementUpdated = false;
+ function Scale() {
+ this.editor = null;
+ this.resizer = null;
+ this.cover = null;
+ this.doc = document;
+ this.prePos = { x: 0, y: 0 };
+ this.startPos = { x: 0, y: 0 };
+ }
+
+ (function() {
+ var rect = [
+ //[left, top, width, height]
+ [0, 0, -1, -1],
+ [0, 0, 0, -1],
+ [0, 0, 1, -1],
+ [0, 0, -1, 0],
+ [0, 0, 1, 0],
+ [0, 0, -1, 1],
+ [0, 0, 0, 1],
+ [0, 0, 1, 1]
+ ];
+
+ Scale.prototype = {
+ init: function(editor) {
+ var me = this;
+ me.editor = editor;
+ me.startPos = this.prePos = { x: 0, y: 0 };
+ me.dragId = -1;
+
+ var hands = [],
+ cover = (me.cover = document.createElement("div")),
+ resizer = (me.resizer = document.createElement("div"));
+
+ cover.id = me.editor.ui.id + "_imagescale_cover";
+ cover.style.cssText =
+ "position:absolute;display:none;z-index:" +
+ me.editor.options.zIndex +
+ ";filter:alpha(opacity=0); opacity:0;background:#CCC;";
+ domUtils.on(cover, "mousedown click", function() {
+ me.hide();
+ });
+
+ for (i = 0; i < 8; i++) {
+ hands.push(
+ ''
+ );
+ }
+ resizer.id = me.editor.ui.id + "_imagescale";
+ resizer.className = "edui-editor-imagescale";
+ resizer.innerHTML = hands.join("");
+ resizer.style.cssText +=
+ ";display:none;border:1px solid #3b77ff;z-index:" +
+ me.editor.options.zIndex +
+ ";";
+
+ me.editor.ui.getDom().appendChild(cover);
+ me.editor.ui.getDom().appendChild(resizer);
+
+ me.initStyle();
+ me.initEvents();
+ },
+ initStyle: function() {
+ utils.cssRule(
+ "imagescale",
+ ".edui-editor-imagescale{display:none;position:absolute;border:1px solid #38B2CE;cursor:hand;-webkit-box-sizing: content-box;-moz-box-sizing: content-box;box-sizing: content-box;}" +
+ ".edui-editor-imagescale span{position:absolute;width:6px;height:6px;overflow:hidden;font-size:0px;display:block;background-color:#3C9DD0;}" +
+ ".edui-editor-imagescale .edui-editor-imagescale-hand0{cursor:nw-resize;top:0;margin-top:-4px;left:0;margin-left:-4px;}" +
+ ".edui-editor-imagescale .edui-editor-imagescale-hand1{cursor:n-resize;top:0;margin-top:-4px;left:50%;margin-left:-4px;}" +
+ ".edui-editor-imagescale .edui-editor-imagescale-hand2{cursor:ne-resize;top:0;margin-top:-4px;left:100%;margin-left:-3px;}" +
+ ".edui-editor-imagescale .edui-editor-imagescale-hand3{cursor:w-resize;top:50%;margin-top:-4px;left:0;margin-left:-4px;}" +
+ ".edui-editor-imagescale .edui-editor-imagescale-hand4{cursor:e-resize;top:50%;margin-top:-4px;left:100%;margin-left:-3px;}" +
+ ".edui-editor-imagescale .edui-editor-imagescale-hand5{cursor:sw-resize;top:100%;margin-top:-3px;left:0;margin-left:-4px;}" +
+ ".edui-editor-imagescale .edui-editor-imagescale-hand6{cursor:s-resize;top:100%;margin-top:-3px;left:50%;margin-left:-4px;}" +
+ ".edui-editor-imagescale .edui-editor-imagescale-hand7{cursor:se-resize;top:100%;margin-top:-3px;left:100%;margin-left:-3px;}"
+ );
+ },
+ initEvents: function() {
+ var me = this;
+
+ me.startPos.x = me.startPos.y = 0;
+ me.isDraging = false;
+ },
+ _eventHandler: function(e) {
+ var me = this;
+ switch (e.type) {
+ case "mousedown":
+ var hand = e.target || e.srcElement,
+ hand;
+ if (
+ hand.className.indexOf("edui-editor-imagescale-hand") != -1 &&
+ me.dragId == -1
+ ) {
+ me.dragId = hand.className.slice(-1);
+ me.startPos.x = me.prePos.x = e.clientX;
+ me.startPos.y = me.prePos.y = e.clientY;
+ domUtils.on(me.doc, "mousemove", me.proxy(me._eventHandler, me));
+ }
+ break;
+ case "mousemove":
+ if (me.dragId != -1) {
+ me.updateContainerStyle(me.dragId, {
+ x: e.clientX - me.prePos.x,
+ y: e.clientY - me.prePos.y
+ });
+ me.prePos.x = e.clientX;
+ me.prePos.y = e.clientY;
+ elementUpdated = true;
+ me.updateTargetElement();
+ }
+ break;
+ case "mouseup":
+ if (me.dragId != -1) {
+ me.updateContainerStyle(me.dragId, {
+ x: e.clientX - me.prePos.x,
+ y: e.clientY - me.prePos.y
+ });
+ me.updateTargetElement();
+ if (me.target.parentNode) me.attachTo(me.target);
+ me.dragId = -1;
+ }
+ domUtils.un(me.doc, "mousemove", me.proxy(me._eventHandler, me));
+ //修复只是点击挪动点,但没有改变大小,不应该触发contentchange
+ if (elementUpdated) {
+ elementUpdated = false;
+ me.editor.fireEvent("contentchange");
+ }
+
+ break;
+ default:
+ break;
+ }
+ },
+ updateTargetElement: function() {
+ var me = this;
+ domUtils.setStyles(me.target, {
+ width: me.resizer.style.width,
+ height: me.resizer.style.height
+ });
+ me.target.width = parseInt(me.resizer.style.width);
+ me.target.height = parseInt(me.resizer.style.height);
+ me.attachTo(me.target);
+ },
+ updateContainerStyle: function(dir, offset) {
+ var me = this,
+ dom = me.resizer,
+ tmp;
+
+ if (rect[dir][0] != 0) {
+ tmp = parseInt(dom.style.left) + offset.x;
+ dom.style.left = me._validScaledProp("left", tmp) + "px";
+ }
+ if (rect[dir][1] != 0) {
+ tmp = parseInt(dom.style.top) + offset.y;
+ dom.style.top = me._validScaledProp("top", tmp) + "px";
+ }
+ if (rect[dir][2] != 0) {
+ tmp = dom.clientWidth + rect[dir][2] * offset.x;
+ dom.style.width = me._validScaledProp("width", tmp) + "px";
+ }
+ if (rect[dir][3] != 0) {
+ tmp = dom.clientHeight + rect[dir][3] * offset.y;
+ dom.style.height = me._validScaledProp("height", tmp) + "px";
+ }
+ },
+ _validScaledProp: function(prop, value) {
+ var ele = this.resizer,
+ wrap = document;
+
+ value = isNaN(value) ? 0 : value;
+ switch (prop) {
+ case "left":
+ return value < 0
+ ? 0
+ : value + ele.clientWidth > wrap.clientWidth
+ ? wrap.clientWidth - ele.clientWidth
+ : value;
+ case "top":
+ return value < 0
+ ? 0
+ : value + ele.clientHeight > wrap.clientHeight
+ ? wrap.clientHeight - ele.clientHeight
+ : value;
+ case "width":
+ return value <= 0
+ ? 1
+ : value + ele.offsetLeft > wrap.clientWidth
+ ? wrap.clientWidth - ele.offsetLeft
+ : value;
+ case "height":
+ return value <= 0
+ ? 1
+ : value + ele.offsetTop > wrap.clientHeight
+ ? wrap.clientHeight - ele.offsetTop
+ : value;
+ }
+ },
+ hideCover: function() {
+ this.cover.style.display = "none";
+ },
+ showCover: function() {
+ var me = this,
+ editorPos = domUtils.getXY(me.editor.ui.getDom()),
+ iframePos = domUtils.getXY(me.editor.iframe);
+
+ domUtils.setStyles(me.cover, {
+ width: me.editor.iframe.offsetWidth + "px",
+ height: me.editor.iframe.offsetHeight + "px",
+ top: iframePos.y - editorPos.y + "px",
+ left: iframePos.x - editorPos.x + "px",
+ position: "absolute",
+ display: ""
+ });
+ },
+ show: function(targetObj) {
+ var me = this;
+ me.resizer.style.display = "block";
+ if (targetObj) me.attachTo(targetObj);
+
+ domUtils.on(this.resizer, "mousedown", me.proxy(me._eventHandler, me));
+ domUtils.on(me.doc, "mouseup", me.proxy(me._eventHandler, me));
+
+ me.showCover();
+ me.editor.fireEvent("afterscaleshow", me);
+ me.editor.fireEvent("saveScene");
+ },
+ hide: function() {
+ var me = this;
+ me.hideCover();
+ me.resizer.style.display = "none";
+
+ domUtils.un(me.resizer, "mousedown", me.proxy(me._eventHandler, me));
+ domUtils.un(me.doc, "mouseup", me.proxy(me._eventHandler, me));
+ me.editor.fireEvent("afterscalehide", me);
+ },
+ proxy: function(fn, context) {
+ return function(e) {
+ return fn.apply(context || this, arguments);
+ };
+ },
+ attachTo: function(targetObj) {
+ var me = this,
+ target = (me.target = targetObj),
+ resizer = this.resizer,
+ imgPos = domUtils.getXY(target),
+ iframePos = domUtils.getXY(me.editor.iframe),
+ editorPos = domUtils.getXY(resizer.parentNode);
+
+ var doc = me.editor.document;
+ domUtils.setStyles(resizer, {
+ width: target.width + "px",
+ height: target.height + "px",
+ left:
+ iframePos.x +
+ imgPos.x -
+ (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0) -
+ editorPos.x -
+ parseInt(resizer.style.borderLeftWidth) +
+ "px",
+ top:
+ iframePos.y +
+ imgPos.y -
+ (doc.documentElement.scrollTop || doc.body.scrollTop || 0) -
+ editorPos.y -
+ parseInt(resizer.style.borderTopWidth) +
+ "px"
+ });
+ }
+ };
+ })();
+
+ return function() {
+ var me = this,
+ imageScale;
+
+ me.setOpt("imageScaleEnabled", true);
+
+ if (!browser.ie && me.options.imageScaleEnabled) {
+ me.addListener("click", function(type, e) {
+ var range = me.selection.getRange(),
+ img = range.getClosedNode();
+
+ if (img && img.tagName == "IMG" && me.body.contentEditable != "false") {
+ if (
+ img.className.indexOf("edui-faked-music") != -1 ||
+ img.getAttribute("anchorname") ||
+ domUtils.hasClass(img, "loadingclass") ||
+ domUtils.hasClass(img, "loaderrorclass")
+ ) {
+ return;
+ }
+
+ if (!imageScale) {
+ imageScale = new Scale();
+ imageScale.init(me);
+ me.ui.getDom().appendChild(imageScale.resizer);
+
+ var _keyDownHandler = function(e) {
+ imageScale.hide();
+ if (imageScale.target)
+ me.selection.getRange().selectNode(imageScale.target).select();
+ },
+ _mouseDownHandler = function(e) {
+ var ele = e.target || e.srcElement;
+ if (
+ ele &&
+ (ele.className === undefined ||
+ ele.className.indexOf("edui-editor-imagescale") == -1)
+ ) {
+ _keyDownHandler(e);
+ }
+ },
+ timer;
+
+ me.addListener("afterscaleshow", function(e) {
+ me.addListener("beforekeydown", _keyDownHandler);
+ me.addListener("beforemousedown", _mouseDownHandler);
+ domUtils.on(document, "keydown", _keyDownHandler);
+ domUtils.on(document, "mousedown", _mouseDownHandler);
+ me.selection.getNative().removeAllRanges();
+ });
+ me.addListener("afterscalehide", function(e) {
+ me.removeListener("beforekeydown", _keyDownHandler);
+ me.removeListener("beforemousedown", _mouseDownHandler);
+ domUtils.un(document, "keydown", _keyDownHandler);
+ domUtils.un(document, "mousedown", _mouseDownHandler);
+ var target = imageScale.target;
+ if (target.parentNode) {
+ me.selection.getRange().selectNode(target).select();
+ }
+ });
+ //TODO 有iframe的情况,mousedown不能往下传。。
+ domUtils.on(imageScale.resizer, "mousedown", function(e) {
+ me.selection.getNative().removeAllRanges();
+ var ele = e.target || e.srcElement;
+ if (
+ ele &&
+ ele.className.indexOf("edui-editor-imagescale-hand") == -1
+ ) {
+ timer = setTimeout(function() {
+ imageScale.hide();
+ if (imageScale.target)
+ me.selection.getRange().selectNode(ele).select();
+ }, 200);
+ }
+ });
+ domUtils.on(imageScale.resizer, "mouseup", function(e) {
+ var ele = e.target || e.srcElement;
+ if (
+ ele &&
+ ele.className.indexOf("edui-editor-imagescale-hand") == -1
+ ) {
+ clearTimeout(timer);
+ }
+ });
+ }
+ imageScale.show(img);
+ } else {
+ if (imageScale && imageScale.resizer.style.display != "none")
+ imageScale.hide();
+ }
+ });
+ }
+
+ if (browser.webkit) {
+ me.addListener("click", function(type, e) {
+ if (e.target.tagName == "IMG" && me.body.contentEditable != "false") {
+ var range = new dom.Range(me.document);
+ range.selectNode(e.target).select();
+ }
+ });
+ }
+ };
+})();
+
+
+// plugins/autolink.js
+///import core
+///commands 为非ie浏览器自动添加a标签
+///commandsName AutoLink
+///commandsTitle 自动增加链接
+/**
+ * @description 为非ie浏览器自动添加a标签
+ * @author zhanyi
+ */
+
+UE.plugin.register(
+ "autolink",
+ function() {
+ var cont = 0;
+
+ return !browser.ie
+ ? {
+ bindEvents: {
+ reset: function() {
+ cont = 0;
+ },
+ keydown: function(type, evt) {
+ var me = this;
+ var keyCode = evt.keyCode || evt.which;
+
+ if (keyCode == 32 || keyCode == 13) {
+ var sel = me.selection.getNative(),
+ range = sel.getRangeAt(0).cloneRange(),
+ offset,
+ charCode;
+
+ var start = range.startContainer;
+ while (start.nodeType == 1 && range.startOffset > 0) {
+ start =
+ range.startContainer.childNodes[range.startOffset - 1];
+ if (!start) {
+ break;
+ }
+ range.setStart(
+ start,
+ start.nodeType == 1
+ ? start.childNodes.length
+ : start.nodeValue.length
+ );
+ range.collapse(true);
+ start = range.startContainer;
+ }
+
+ do {
+ if (range.startOffset == 0) {
+ start = range.startContainer.previousSibling;
+
+ while (start && start.nodeType == 1) {
+ start = start.lastChild;
+ }
+ if (!start || domUtils.isFillChar(start)) {
+ break;
+ }
+ offset = start.nodeValue.length;
+ } else {
+ start = range.startContainer;
+ offset = range.startOffset;
+ }
+ range.setStart(start, offset - 1);
+ charCode = range.toString().charCodeAt(0);
+ } while (charCode != 160 && charCode != 32);
+
+ if (
+ range
+ .toString()
+ .replace(new RegExp(domUtils.fillChar, "g"), "")
+ .match(/(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i)
+ ) {
+ while (range.toString().length) {
+ if (
+ /^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i.test(
+ range.toString()
+ )
+ ) {
+ break;
+ }
+ try {
+ range.setStart(
+ range.startContainer,
+ range.startOffset + 1
+ );
+ } catch (e) {
+ //trace:2121
+ var start = range.startContainer;
+ while (!(next = start.nextSibling)) {
+ if (domUtils.isBody(start)) {
+ return;
+ }
+ start = start.parentNode;
+ }
+ range.setStart(next, 0);
+ }
+ }
+ //range的开始边界已经在a标签里的不再处理
+ if (
+ domUtils.findParentByTagName(
+ range.startContainer,
+ "a",
+ true
+ )
+ ) {
+ return;
+ }
+ var a = me.document.createElement("a"),
+ text = me.document.createTextNode(" "),
+ href;
+
+ me.undoManger && me.undoManger.save();
+ a.appendChild(range.extractContents());
+ a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g, "");
+ href = a
+ .getAttribute("href")
+ .replace(new RegExp(domUtils.fillChar, "g"), "");
+ href = /^(?:https?:\/\/)/gi.test(href)
+ ? href
+ : "http://" + href;
+ a.setAttribute("_src", utils.html(href));
+ a.href = utils.html(href);
+
+ range.insertNode(a);
+ a.parentNode.insertBefore(text, a.nextSibling);
+ range.setStart(text, 0);
+ range.collapse(true);
+ sel.removeAllRanges();
+ sel.addRange(range);
+ me.undoManger && me.undoManger.save();
+ }
+ }
+ }
+ }
+ }
+ : {};
+ },
+ function() {
+ var keyCodes = {
+ 37: 1,
+ 38: 1,
+ 39: 1,
+ 40: 1,
+ 13: 1,
+ 32: 1
+ };
+ function checkIsCludeLink(node) {
+ if (node.nodeType == 3) {
+ return null;
+ }
+ if (node.nodeName == "A") {
+ return node;
+ }
+ var lastChild = node.lastChild;
+
+ while (lastChild) {
+ if (lastChild.nodeName == "A") {
+ return lastChild;
+ }
+ if (lastChild.nodeType == 3) {
+ if (domUtils.isWhitespace(lastChild)) {
+ lastChild = lastChild.previousSibling;
+ continue;
+ }
+ return null;
+ }
+ lastChild = lastChild.lastChild;
+ }
+ }
+ browser.ie &&
+ this.addListener("keyup", function(cmd, evt) {
+ var me = this,
+ keyCode = evt.keyCode;
+ if (keyCodes[keyCode]) {
+ var rng = me.selection.getRange();
+ var start = rng.startContainer;
+
+ if (keyCode == 13) {
+ while (
+ start &&
+ !domUtils.isBody(start) &&
+ !domUtils.isBlockElm(start)
+ ) {
+ start = start.parentNode;
+ }
+ if (start && !domUtils.isBody(start) && start.nodeName == "P") {
+ var pre = start.previousSibling;
+ if (pre && pre.nodeType == 1) {
+ var pre = checkIsCludeLink(pre);
+ if (pre && !pre.getAttribute("_href")) {
+ domUtils.remove(pre, true);
+ }
+ }
+ }
+ } else if (keyCode == 32) {
+ if (start.nodeType == 3 && /^\s$/.test(start.nodeValue)) {
+ start = start.previousSibling;
+ if (
+ start &&
+ start.nodeName == "A" &&
+ !start.getAttribute("_href")
+ ) {
+ domUtils.remove(start, true);
+ }
+ }
+ } else {
+ start = domUtils.findParentByTagName(start, "a", true);
+ if (start && !start.getAttribute("_href")) {
+ var bk = rng.createBookmark();
+
+ domUtils.remove(start, true);
+ rng.moveToBookmark(bk).select(true);
+ }
+ }
+ }
+ });
+ }
+);
+
+
+// plugins/autoheight.js
+///import core
+///commands 当输入内容超过编辑器高度时,编辑器自动增高
+///commandsName AutoHeight,autoHeightEnabled
+///commandsTitle 自动增高
+/**
+ * @description 自动伸展
+ * @author zhanyi
+ */
+UE.plugins["autoheight"] = function() {
+ var me = this;
+ //提供开关,就算加载也可以关闭
+ me.autoHeightEnabled = me.options.autoHeightEnabled !== false;
+ if (!me.autoHeightEnabled) {
+ return;
+ }
+
+ var bakOverflow,
+ lastHeight = 0,
+ options = me.options,
+ currentHeight,
+ timer;
+
+ function adjustHeight() {
+ var me = this;
+ clearTimeout(timer);
+ if (isFullscreen) return;
+ if (
+ !me.queryCommandState ||
+ (me.queryCommandState && me.queryCommandState("source") != 1)
+ ) {
+ timer = setTimeout(function() {
+ var node = me.body.lastChild;
+ while (node && node.nodeType != 1) {
+ node = node.previousSibling;
+ }
+ if (node && node.nodeType == 1) {
+ node.style.clear = "both";
+ currentHeight = Math.max(
+ domUtils.getXY(node).y + node.offsetHeight + 25,
+ Math.max(options.minFrameHeight, options.initialFrameHeight)
+ );
+ if (currentHeight != lastHeight) {
+ if (currentHeight !== parseInt(me.iframe.parentNode.style.height)) {
+ me.iframe.parentNode.style.height = currentHeight + "px";
+ }
+ me.body.style.height = currentHeight + "px";
+ lastHeight = currentHeight;
+ }
+ domUtils.removeStyle(node, "clear");
+ }
+ }, 50);
+ }
+ }
+ var isFullscreen;
+ me.addListener("fullscreenchanged", function(cmd, f) {
+ isFullscreen = f;
+ });
+ me.addListener("destroy", function() {
+ domUtils.un(me.window, "scroll", fixedScrollTop);
+ me.removeListener(
+ "contentchange afterinserthtml keyup mouseup",
+ adjustHeight
+ );
+ });
+ me.enableAutoHeight = function() {
+ var me = this;
+ if (!me.autoHeightEnabled) {
+ return;
+ }
+ var doc = me.document;
+ me.autoHeightEnabled = true;
+ bakOverflow = doc.body.style.overflowY;
+ doc.body.style.overflowY = "hidden";
+ me.addListener("contentchange afterinserthtml keyup mouseup", adjustHeight);
+ //ff不给事件算得不对
+
+ setTimeout(function() {
+ adjustHeight.call(me);
+ }, browser.gecko ? 100 : 0);
+ me.fireEvent("autoheightchanged", me.autoHeightEnabled);
+ };
+ me.disableAutoHeight = function() {
+ me.body.style.overflowY = bakOverflow || "";
+
+ me.removeListener("contentchange", adjustHeight);
+ me.removeListener("keyup", adjustHeight);
+ me.removeListener("mouseup", adjustHeight);
+ me.autoHeightEnabled = false;
+ me.fireEvent("autoheightchanged", me.autoHeightEnabled);
+ };
+
+ me.on("setHeight", function() {
+ me.disableAutoHeight();
+ });
+ me.addListener("ready", function() {
+ me.enableAutoHeight();
+ //trace:1764
+ var timer;
+ domUtils.on(
+ browser.ie ? me.body : me.document,
+ browser.webkit ? "dragover" : "drop",
+ function() {
+ clearTimeout(timer);
+ timer = setTimeout(function() {
+ //trace:3681
+ adjustHeight.call(me);
+ }, 100);
+ }
+ );
+ //修复内容过多时,回到顶部,顶部内容被工具栏遮挡问题
+ domUtils.on(me.window, "scroll", fixedScrollTop);
+ });
+
+ var lastScrollY;
+
+ function fixedScrollTop() {
+ if (!me.window) return;
+ if (lastScrollY === null) {
+ lastScrollY = me.window.scrollY;
+ } else if (me.window.scrollY == 0 && lastScrollY != 0) {
+ me.window.scrollTo(0, 0);
+ lastScrollY = null;
+ }
+ }
+};
+
+
+// plugins/autofloat.js
+///import core
+///commands 悬浮工具栏
+///commandsName AutoFloat,autoFloatEnabled
+///commandsTitle 悬浮工具栏
+/**
+ * modified by chengchao01
+ * 注意: 引入此功能后,在IE6下会将body的背景图片覆盖掉!
+ */
+UE.plugins["autofloat"] = function() {
+ var me = this,
+ lang = me.getLang();
+ me.setOpt({
+ topOffset: 0
+ });
+ var optsAutoFloatEnabled = me.options.autoFloatEnabled !== false,
+ topOffset = me.options.topOffset;
+
+ //如果不固定toolbar的位置,则直接退出
+ if (!optsAutoFloatEnabled) {
+ return;
+ }
+ var uiUtils = UE.ui.uiUtils,
+ LteIE6 = browser.ie && browser.version <= 6,
+ quirks = browser.quirks;
+
+ function checkHasUI() {
+ if (!UE.ui) {
+ alert(lang.autofloatMsg);
+ return 0;
+ }
+ return 1;
+ }
+ function fixIE6FixedPos() {
+ var docStyle = document.body.style;
+ docStyle.backgroundImage = 'url("about:blank")';
+ docStyle.backgroundAttachment = "fixed";
+ }
+ var bakCssText,
+ placeHolder = document.createElement("div"),
+ toolbarBox,
+ orgTop,
+ getPosition,
+ flag = true; //ie7模式下需要偏移
+ function setFloating() {
+ var toobarBoxPos = domUtils.getXY(toolbarBox),
+ origalFloat = domUtils.getComputedStyle(toolbarBox, "position"),
+ origalLeft = domUtils.getComputedStyle(toolbarBox, "left");
+ toolbarBox.style.width = toolbarBox.offsetWidth + "px";
+ toolbarBox.style.zIndex = me.options.zIndex * 1 + 1;
+ toolbarBox.parentNode.insertBefore(placeHolder, toolbarBox);
+ if (LteIE6 || (quirks && browser.ie)) {
+ if (toolbarBox.style.position != "absolute") {
+ toolbarBox.style.position = "absolute";
+ }
+ toolbarBox.style.top =
+ (document.body.scrollTop || document.documentElement.scrollTop) -
+ orgTop +
+ topOffset +
+ "px";
+ } else {
+ if (browser.ie7Compat && flag) {
+ flag = false;
+ toolbarBox.style.left =
+ domUtils.getXY(toolbarBox).x -
+ document.documentElement.getBoundingClientRect().left +
+ 2 +
+ "px";
+ }
+ if (toolbarBox.style.position != "fixed") {
+ toolbarBox.style.position = "fixed";
+ toolbarBox.style.top = topOffset + "px";
+ (origalFloat == "absolute" || origalFloat == "relative") &&
+ parseFloat(origalLeft) &&
+ (toolbarBox.style.left = toobarBoxPos.x + "px");
+ }
+ }
+ }
+ function unsetFloating() {
+ flag = true;
+ if (placeHolder.parentNode) {
+ placeHolder.parentNode.removeChild(placeHolder);
+ }
+
+ toolbarBox.style.cssText = bakCssText;
+ }
+
+ function updateFloating() {
+ var rect3 = getPosition(me.container);
+ var offset = me.options.toolbarTopOffset || 0;
+ if (rect3.top < 0 && rect3.bottom - toolbarBox.offsetHeight > offset) {
+ setFloating();
+ } else {
+ unsetFloating();
+ }
+ }
+ var defer_updateFloating = utils.defer(
+ function() {
+ updateFloating();
+ },
+ browser.ie ? 200 : 100,
+ true
+ );
+
+ me.addListener("destroy", function() {
+ domUtils.un(window, ["scroll", "resize"], updateFloating);
+ me.removeListener("keydown", defer_updateFloating);
+ //适用于在DIV scrollbox中滚动,但页面不滚动的浮动toolbar
+ var scrollBox = document.getElementById("scrollBox");
+ if (scrollBox) {
+ domUtils.un(scrollBox, ['scroll','resize'], updateFloating);
+ }
+ });
+
+ me.addListener("ready", function() {
+ if (checkHasUI(me)) {
+ //加载了ui组件,但在new时,没有加载ui,导致编辑器实例上没有ui类,所以这里做判断
+ if (!me.ui) {
+ return;
+ }
+ getPosition = uiUtils.getClientRect;
+ toolbarBox = me.ui.getDom("toolbarbox");
+ orgTop = getPosition(toolbarBox).top;
+ bakCssText = toolbarBox.style.cssText;
+ placeHolder.style.height = me.ui.getDom("iframeholder").offsetHeight + "px";
+ if (LteIE6) {
+ fixIE6FixedPos();
+ }
+ domUtils.on(window, ["scroll", "resize"], updateFloating);
+ me.addListener("keydown", defer_updateFloating);
+ //适用于在DIV scrollbox中滚动,但页面不滚动的浮动toolbar
+ var scrollBox = document.getElementById("scrollBox");
+ if (scrollBox) {
+ domUtils.on(scrollBox, ['scroll','resize'], updateFloating);
+ }
+ me.addListener("beforefullscreenchange", function(t, enabled) {
+ if (enabled) {
+ unsetFloating();
+ }
+ });
+ me.addListener("fullscreenchanged", function(t, enabled) {
+ if (!enabled) {
+ updateFloating();
+ }
+ });
+ me.addListener("sourcemodechanged", function(t, enabled) {
+ setTimeout(function() {
+ updateFloating();
+ }, 0);
+ });
+ me.addListener("clearDoc", function() {
+ setTimeout(function() {
+ updateFloating();
+ }, 0);
+ });
+ }
+ });
+};
+
+
+// plugins/video.js
+/**
+ * video插件, 为UEditor提供视频插入支持
+ * @file
+ * @since 1.2.6.1
+ */
+
+UE.plugins["video"] = function() {
+ var me = this;
+
+ /**
+ * 创建插入视频字符窜
+ * @param url 视频地址
+ * @param width 视频宽度
+ * @param height 视频高度
+ * @param align 视频对齐
+ * @param toEmbed 是否以flash代替显示
+ * @param addParagraph 是否需要添加P 标签
+ */
+ function creatInsertStr(url, width, height, id, align, classname, type) {
+ var str;
+ switch (type) {
+ case "image":
+ str =
+ " ';
+ break;
+ case "embed":
+ str =
+ ' |