diff --git a/vendor/ueditor/ueditor.all.js b/vendor/ueditor/ueditor.all.js
index 4bf58480..a1139a1f 100644
--- a/vendor/ueditor/ueditor.all.js
+++ b/vendor/ueditor/ueditor.all.js
@@ -1,12 +1,12 @@
-/*!
- * UEditor
- * version: ueditor
- * build: Mon Jan 07 2019 11:39:49 GMT+0800 (CST)
- */
-
-(function(){
-
-// editor.js
+/*!
+ * UEditor
+ * version: ueditor
+ * build: Mon Jan 07 2019 11:39:49 GMT+0800 (CST)
+ */
+
+(function(){
+
+// editor.js
UEDITOR_CONFIG = window.UEDITOR_CONFIG || {};
var baidu = window.baidu || {};
@@ -27,9 +27,9 @@ UE._customizeUI = {};
UE.version = "1.4.3";
-var dom = UE.dom = {};
-
-// core/browser.js
+var dom = UE.dom = {};
+
+// core/browser.js
/**
* 浏览器判断模块
* @file
@@ -287,9 +287,9 @@ var browser = UE.browser = function(){
var ie = browser.ie,
webkit = browser.webkit,
gecko = browser.gecko,
- opera = browser.opera;
-
-// core/utils.js
+ opera = browser.opera;
+
+// core/utils.js
/**
* 工具函数包
* @file
@@ -1522,9 +1522,9 @@ utils.each(['String', 'Function', 'Array', 'Number', 'RegExp', 'Object', 'Date']
return Object.prototype.toString.apply(obj) == '[object ' + v + ']';
}
});
-
-
-// core/EventBase.js
+
+
+// core/EventBase.js
/**
* UE采用的事件基类
* @file
@@ -1692,9 +1692,9 @@ function getListener(obj, type, force) {
&& ( allListeners[type] || force && ( allListeners[type] = [] ) ) );
}
-
-
-// core/dtd.js
+
+
+// core/dtd.js
///import editor.js
///import core/dom/dom.js
///import core/utils.js
@@ -1874,9 +1874,9 @@ var dtd = dom.dtd = (function() {
dfn : L
});
})();
-
-
-// core/domUtils.js
+
+
+// core/domUtils.js
/**
* Dom操作工具包
* @file
@@ -4290,9 +4290,9 @@ var domUtils = dom.domUtils = {
},
fillHtml : browser.ie11below ? ' ' : '
'
};
-var fillCharReg = new RegExp(domUtils.fillChar, 'g');
-
-// core/Range.js
+var fillCharReg = new RegExp(domUtils.fillChar, 'g');
+
+// core/Range.js
/**
* Range封装
* @file
@@ -6137,9 +6137,9 @@ var fillCharReg = new RegExp(domUtils.fillChar, 'g');
return this.moveToBookmark(bookmark);
}
};
-})();
-
-// core/Selection.js
+})();
+
+// core/Selection.js
/**
* 选集
* @file
@@ -6528,9 +6528,9 @@ var fillCharReg = new RegExp(domUtils.fillChar, 'g');
this.getNative()[browser.ie9below ? 'empty' : 'removeAllRanges']();
}
};
-})();
-
-// core/Editor.js
+})();
+
+// core/Editor.js
/**
* 编辑器主类,包含编辑器提供的大部分公用接口
* @file
@@ -8067,111 +8067,111 @@ var fillCharReg = new RegExp(domUtils.fillChar, 'g');
};
utils.inherits(Editor, EventBase);
})();
-
-
-// core/Editor.defaultoptions.js
-//维护编辑器一下默认的不在插件中的配置项
-UE.Editor.defaultOptions = function(editor){
-
- var _url = editor.options.UEDITOR_HOME_URL;
- return {
- isShow: true,
- initialContent: '',
- initialStyle:'',
- autoClearinitialContent: false,
- iframeCssUrl: _url + 'themes/iframe.css',
- textarea: 'editorValue',
- focus: false,
- focusInEnd: true,
- autoClearEmptyNode: true,
- fullscreen: false,
- readonly: false,
- zIndex: 999,
- imagePopup: true,
- enterTag: 'p',
- customDomain: false,
- lang: 'zh-cn',
- langPath: _url + 'lang/',
- theme: 'default',
- themePath: _url + 'themes/',
- allHtmlEnabled: false,
- scaleEnabled: false,
- tableNativeEditInFF: false,
- autoSyncData : true,
- fileNameFormat: '{time}{rand:6}'
- }
-};
-
-// core/loadconfig.js
-(function(){
-
- UE.Editor.prototype.loadServerConfig = function(){
- var me = this;
- setTimeout(function(){
- try{
- me.options.imageUrl && me.setOpt('serverUrl', me.options.imageUrl.replace(/^(.*[\/]).+([\.].+)$/, '$1controller$2'));
-
- var configUrl = me.getActionUrl('config'),
- isJsonp = utils.isCrossDomainUrl(configUrl);
-
- /* 发出ajax请求 */
- me._serverConfigLoaded = false;
-
- configUrl && UE.ajax.request(configUrl,{
- 'method': 'GET',
- 'dataType': isJsonp ? 'jsonp':'',
- 'onsuccess':function(r){
- try {
- var config = isJsonp ? r:eval("("+r.responseText+")");
- utils.extend(me.options, config);
- me.fireEvent('serverConfigLoaded');
- me._serverConfigLoaded = true;
- } catch (e) {
- showErrorMsg(me.getLang('loadconfigFormatError'));
- }
- },
- 'onerror':function(){
- showErrorMsg(me.getLang('loadconfigHttpError'));
- }
- });
- } catch(e){
- showErrorMsg(me.getLang('loadconfigError'));
- }
- });
-
- function showErrorMsg(msg) {
- console && msg && console.error(msg);
- //me.fireEvent('showMessage', {
- // 'title': msg,
- // 'type': 'error'
- //});
- }
- };
-
- UE.Editor.prototype.isServerConfigLoaded = function(){
- var me = this;
- return me._serverConfigLoaded || false;
- };
-
- UE.Editor.prototype.afterConfigReady = function(handler){
- if (!handler || !utils.isFunction(handler)) return;
- var me = this;
- var readyHandler = function(){
- handler.apply(me, arguments);
- me.removeListener('serverConfigLoaded', readyHandler);
- };
-
- if (me.isServerConfigLoaded()) {
- handler.call(me, 'serverConfigLoaded');
- } else {
- me.addListener('serverConfigLoaded', readyHandler);
- }
- };
-
-})();
-
-
-// core/ajax.js
+
+
+// core/Editor.defaultoptions.js
+//维护编辑器一下默认的不在插件中的配置项
+UE.Editor.defaultOptions = function(editor){
+
+ var _url = editor.options.UEDITOR_HOME_URL;
+ return {
+ isShow: true,
+ initialContent: '',
+ initialStyle:'',
+ autoClearinitialContent: false,
+ iframeCssUrl: _url + 'themes/iframe.css',
+ textarea: 'editorValue',
+ focus: false,
+ focusInEnd: true,
+ autoClearEmptyNode: true,
+ fullscreen: false,
+ readonly: false,
+ zIndex: 999,
+ imagePopup: true,
+ enterTag: 'p',
+ customDomain: false,
+ lang: 'zh-cn',
+ langPath: _url + 'lang/',
+ theme: 'default',
+ themePath: _url + 'themes/',
+ allHtmlEnabled: false,
+ scaleEnabled: false,
+ tableNativeEditInFF: false,
+ autoSyncData : true,
+ fileNameFormat: '{time}{rand:6}'
+ }
+};
+
+// core/loadconfig.js
+(function(){
+
+ UE.Editor.prototype.loadServerConfig = function(){
+ var me = this;
+ setTimeout(function(){
+ try{
+ me.options.imageUrl && me.setOpt('serverUrl', me.options.imageUrl.replace(/^(.*[\/]).+([\.].+)$/, '$1controller$2'));
+
+ var configUrl = me.getActionUrl('config'),
+ isJsonp = utils.isCrossDomainUrl(configUrl);
+
+ /* 发出ajax请求 */
+ me._serverConfigLoaded = false;
+
+ configUrl && UE.ajax.request(configUrl,{
+ 'method': 'GET',
+ 'dataType': isJsonp ? 'jsonp':'',
+ 'onsuccess':function(r){
+ try {
+ var config = isJsonp ? r:eval("("+r.responseText+")");
+ utils.extend(me.options, config);
+ me.fireEvent('serverConfigLoaded');
+ me._serverConfigLoaded = true;
+ } catch (e) {
+ showErrorMsg(me.getLang('loadconfigFormatError'));
+ }
+ },
+ 'onerror':function(){
+ showErrorMsg(me.getLang('loadconfigHttpError'));
+ }
+ });
+ } catch(e){
+ showErrorMsg(me.getLang('loadconfigError'));
+ }
+ });
+
+ function showErrorMsg(msg) {
+ console && msg && console.error(msg);
+ //me.fireEvent('showMessage', {
+ // 'title': msg,
+ // 'type': 'error'
+ //});
+ }
+ };
+
+ UE.Editor.prototype.isServerConfigLoaded = function(){
+ var me = this;
+ return me._serverConfigLoaded || false;
+ };
+
+ UE.Editor.prototype.afterConfigReady = function(handler){
+ if (!handler || !utils.isFunction(handler)) return;
+ var me = this;
+ var readyHandler = function(){
+ handler.apply(me, arguments);
+ me.removeListener('serverConfigLoaded', readyHandler);
+ };
+
+ if (me.isServerConfigLoaded()) {
+ handler.call(me, 'serverConfigLoaded');
+ } else {
+ me.addListener('serverConfigLoaded', readyHandler);
+ }
+ };
+
+})();
+
+
+// core/ajax.js
/**
* @file
* @module UE.ajax
@@ -8434,9 +8434,9 @@ UE.ajax = function() {
}();
-
-
-// core/filterword.js
+
+
+// core/filterword.js
/**
* UE过滤word的静态方法
* @file
@@ -8625,20979 +8625,20979 @@ var filterWord = UE.filterWord = function () {
return function ( html ) {
return (isWordDocument( html ) ? filterPasteWord( html ) : html);
};
-}();
-
-// core/node.js
-/**
- * 编辑器模拟的节点类
- * @file
- * @module UE
- * @class uNode
- * @since 1.2.6.1
- */
-
-/**
- * UEditor公用空间,UEditor所有的功能都挂载在该空间下
- * @unfile
- * @module UE
- */
-
-(function () {
-
- /**
- * 编辑器模拟的节点类
- * @unfile
- * @module UE
- * @class uNode
- */
-
- /**
- * 通过一个键值对,创建一个uNode对象
- * @constructor
- * @param { Object } attr 传入要创建的uNode的初始属性
- * @example
- * ```javascript
- * var node = new uNode({
- * type:'element',
- * tagName:'span',
- * attrs:{style:'font-size:14px;'}
- * }
- * ```
- */
- var uNode = UE.uNode = function (obj) {
- this.type = obj.type;
- this.data = obj.data;
- this.tagName = obj.tagName;
- this.parentNode = obj.parentNode;
- this.attrs = obj.attrs || {};
- this.children = obj.children;
- };
-
- var notTransAttrs = {
- 'href':1,
- 'src':1,
- '_src':1,
- '_href':1,
- 'cdata_data':1
- };
-
- var notTransTagName = {
- style:1,
- script:1
- };
-
- var indentChar = ' ',
- breakChar = '\n';
-
- function insertLine(arr, current, begin) {
- arr.push(breakChar);
- return current + (begin ? 1 : -1);
- }
-
- function insertIndent(arr, current) {
- //插入缩进
- for (var i = 0; i < current; i++) {
- arr.push(indentChar);
- }
- }
-
- //创建uNode的静态方法
- //支持标签和html
- uNode.createElement = function (html) {
- if (/[<>]/.test(html)) {
- return UE.htmlparser(html).children[0]
- } else {
- return new uNode({
- type:'element',
- children:[],
- tagName:html
- })
- }
- };
- uNode.createText = function (data,noTrans) {
- return new UE.uNode({
- type:'text',
- 'data':noTrans ? data : utils.unhtml(data || '')
- })
- };
- function nodeToHtml(node, arr, formatter, current) {
- switch (node.type) {
- case 'root':
- for (var i = 0, ci; ci = node.children[i++];) {
- //插入新行
- if (formatter && ci.type == 'element' && !dtd.$inlineWithA[ci.tagName] && i > 1) {
- insertLine(arr, current, true);
- insertIndent(arr, current)
- }
- nodeToHtml(ci, arr, formatter, current)
- }
- break;
- case 'text':
- isText(node, arr);
- break;
- case 'element':
- isElement(node, arr, formatter, current);
- break;
- case 'comment':
- isComment(node, arr, formatter);
- }
- return arr;
- }
-
- function isText(node, arr) {
- if(node.parentNode.tagName == 'pre'){
- //源码模式下输入html标签,不能做转换处理,直接输出
- arr.push(node.data)
- }else{
- arr.push(notTransTagName[node.parentNode.tagName] ? utils.html(node.data) : node.data.replace(/[ ]{2}/g,' '))
- }
-
- }
-
- function isElement(node, arr, formatter, current) {
- var attrhtml = '';
- if (node.attrs) {
- attrhtml = [];
- var attrs = node.attrs;
- for (var a in attrs) {
- //这里就针对
- //
'
- //这里边的\"做转换,要不用innerHTML直接被截断了,属性src
- //有可能做的不够
- attrhtml.push(a + (attrs[a] !== undefined ? '="' + (notTransAttrs[a] ? utils.html(attrs[a]).replace(/["]/g, function (a) {
- return '"'
- }) : utils.unhtml(attrs[a])) + '"' : ''))
- }
- attrhtml = attrhtml.join(' ');
- }
- arr.push('<' + node.tagName +
- (attrhtml ? ' ' + attrhtml : '') +
- (dtd.$empty[node.tagName] ? '\/' : '' ) + '>'
- );
- //插入新行
- if (formatter && !dtd.$inlineWithA[node.tagName] && node.tagName != 'pre') {
- if(node.children && node.children.length){
- current = insertLine(arr, current, true);
- insertIndent(arr, current)
- }
-
- }
- if (node.children && node.children.length) {
- for (var i = 0, ci; ci = node.children[i++];) {
- if (formatter && ci.type == 'element' && !dtd.$inlineWithA[ci.tagName] && i > 1) {
- insertLine(arr, current);
- insertIndent(arr, current)
- }
- nodeToHtml(ci, arr, formatter, current)
- }
- }
- if (!dtd.$empty[node.tagName]) {
- if (formatter && !dtd.$inlineWithA[node.tagName] && node.tagName != 'pre') {
-
- if(node.children && node.children.length){
- current = insertLine(arr, current);
- insertIndent(arr, current)
- }
- }
- arr.push('<\/' + node.tagName + '>');
- }
-
- }
-
- function isComment(node, arr) {
- arr.push('');
- }
-
- function getNodeById(root, id) {
- var node;
- if (root.type == 'element' && root.getAttr('id') == id) {
- return root;
- }
- if (root.children && root.children.length) {
- for (var i = 0, ci; ci = root.children[i++];) {
- if (node = getNodeById(ci, id)) {
- return node;
- }
- }
- }
- }
-
- function getNodesByTagName(node, tagName, arr) {
- if (node.type == 'element' && node.tagName == tagName) {
- arr.push(node);
- }
- if (node.children && node.children.length) {
- for (var i = 0, ci; ci = node.children[i++];) {
- getNodesByTagName(ci, tagName, arr)
- }
- }
- }
- function nodeTraversal(root,fn){
- if(root.children && root.children.length){
- for(var i= 0,ci;ci=root.children[i];){
- nodeTraversal(ci,fn);
- //ci被替换的情况,这里就不再走 fn了
- if(ci.parentNode ){
- if(ci.children && ci.children.length){
- fn(ci)
- }
- if(ci.parentNode) i++
- }
- }
- }else{
- fn(root)
- }
-
- }
- uNode.prototype = {
-
- /**
- * 当前节点对象,转换成html文本
- * @method toHtml
- * @return { String } 返回转换后的html字符串
- * @example
- * ```javascript
- * node.toHtml();
- * ```
- */
-
- /**
- * 当前节点对象,转换成html文本
- * @method toHtml
- * @param { Boolean } formatter 是否格式化返回值
- * @return { String } 返回转换后的html字符串
- * @example
- * ```javascript
- * node.toHtml( true );
- * ```
- */
- toHtml:function (formatter) {
- var arr = [];
- nodeToHtml(this, arr, formatter, 0);
- return arr.join('')
- },
-
- /**
- * 获取节点的html内容
- * @method innerHTML
- * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点
- * @return { String } 返回节点的html内容
- * @example
- * ```javascript
- * var htmlstr = node.innerHTML();
- * ```
- */
-
- /**
- * 设置节点的html内容
- * @method innerHTML
- * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点
- * @param { String } htmlstr 传入要设置的html内容
- * @return { UE.uNode } 返回节点本身
- * @example
- * ```javascript
- * node.innerHTML('text');
- * ```
- */
- innerHTML:function (htmlstr) {
- if (this.type != 'element' || dtd.$empty[this.tagName]) {
- return this;
- }
- if (utils.isString(htmlstr)) {
- if(this.children){
- for (var i = 0, ci; ci = this.children[i++];) {
- ci.parentNode = null;
- }
- }
- this.children = [];
- var tmpRoot = UE.htmlparser(htmlstr);
- for (var i = 0, ci; ci = tmpRoot.children[i++];) {
- this.children.push(ci);
- ci.parentNode = this;
- }
- return this;
- } else {
- var tmpRoot = new UE.uNode({
- type:'root',
- children:this.children
- });
- return tmpRoot.toHtml();
- }
- },
-
- /**
- * 获取节点的纯文本内容
- * @method innerText
- * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点
- * @return { String } 返回节点的存文本内容
- * @example
- * ```javascript
- * var textStr = node.innerText();
- * ```
- */
-
- /**
- * 设置节点的纯文本内容
- * @method innerText
- * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点
- * @param { String } textStr 传入要设置的文本内容
- * @return { UE.uNode } 返回节点本身
- * @example
- * ```javascript
- * node.innerText('text');
- * ```
- */
- innerText:function (textStr,noTrans) {
- if (this.type != 'element' || dtd.$empty[this.tagName]) {
- return this;
- }
- if (textStr) {
- if(this.children){
- for (var i = 0, ci; ci = this.children[i++];) {
- ci.parentNode = null;
- }
- }
- this.children = [];
- this.appendChild(uNode.createText(textStr,noTrans));
- return this;
- } else {
- return this.toHtml().replace(/<[^>]+>/g, '');
- }
- },
-
- /**
- * 获取当前对象的data属性
- * @method getData
- * @return { Object } 若节点的type值是elemenet,返回空字符串,否则返回节点的data属性
- * @example
- * ```javascript
- * node.getData();
- * ```
- */
- getData:function () {
- if (this.type == 'element')
- return '';
- return this.data
- },
-
- /**
- * 获取当前节点下的第一个子节点
- * @method firstChild
- * @return { UE.uNode } 返回第一个子节点
- * @example
- * ```javascript
- * node.firstChild(); //返回第一个子节点
- * ```
- */
- firstChild:function () {
-// if (this.type != 'element' || dtd.$empty[this.tagName]) {
-// return this;
-// }
- return this.children ? this.children[0] : null;
- },
-
- /**
- * 获取当前节点下的最后一个子节点
- * @method lastChild
- * @return { UE.uNode } 返回最后一个子节点
- * @example
- * ```javascript
- * node.lastChild(); //返回最后一个子节点
- * ```
- */
- lastChild:function () {
-// if (this.type != 'element' || dtd.$empty[this.tagName] ) {
-// return this;
-// }
- return this.children ? this.children[this.children.length - 1] : null;
- },
-
- /**
- * 获取和当前节点有相同父亲节点的前一个节点
- * @method previousSibling
- * @return { UE.uNode } 返回前一个节点
- * @example
- * ```javascript
- * node.children[2].previousSibling(); //返回子节点node.children[1]
- * ```
- */
- previousSibling : function(){
- var parent = this.parentNode;
- for (var i = 0, ci; ci = parent.children[i]; i++) {
- if (ci === this) {
- return i == 0 ? null : parent.children[i-1];
- }
- }
-
- },
-
- /**
- * 获取和当前节点有相同父亲节点的后一个节点
- * @method nextSibling
- * @return { UE.uNode } 返回后一个节点,找不到返回null
- * @example
- * ```javascript
- * node.children[2].nextSibling(); //如果有,返回子节点node.children[3]
- * ```
- */
- nextSibling : function(){
- var parent = this.parentNode;
- for (var i = 0, ci; ci = parent.children[i++];) {
- if (ci === this) {
- return parent.children[i];
- }
- }
- },
-
- /**
- * 用新的节点替换当前节点
- * @method replaceChild
- * @param { UE.uNode } target 要替换成该节点参数
- * @param { UE.uNode } source 要被替换掉的节点
- * @return { UE.uNode } 返回替换之后的节点对象
- * @example
- * ```javascript
- * node.replaceChild(newNode, childNode); //用newNode替换childNode,childNode是node的子节点
- * ```
- */
- replaceChild:function (target, source) {
- if (this.children) {
- if(target.parentNode){
- target.parentNode.removeChild(target);
- }
- for (var i = 0, ci; ci = this.children[i]; i++) {
- if (ci === source) {
- this.children.splice(i, 1, target);
- source.parentNode = null;
- target.parentNode = this;
- return target;
- }
- }
- }
- },
-
- /**
- * 在节点的子节点列表最后位置插入一个节点
- * @method appendChild
- * @param { UE.uNode } node 要插入的节点
- * @return { UE.uNode } 返回刚插入的子节点
- * @example
- * ```javascript
- * node.appendChild( newNode ); //在node内插入子节点newNode
- * ```
- */
- appendChild:function (node) {
- if (this.type == 'root' || (this.type == 'element' && !dtd.$empty[this.tagName])) {
- if (!this.children) {
- this.children = []
- }
- if(node.parentNode){
- node.parentNode.removeChild(node);
- }
- for (var i = 0, ci; ci = this.children[i]; i++) {
- if (ci === node) {
- this.children.splice(i, 1);
- break;
- }
- }
- this.children.push(node);
- node.parentNode = this;
- return node;
- }
-
-
- },
-
- /**
- * 在传入节点的前面插入一个节点
- * @method insertBefore
- * @param { UE.uNode } target 要插入的节点
- * @param { UE.uNode } source 在该参数节点前面插入
- * @return { UE.uNode } 返回刚插入的子节点
- * @example
- * ```javascript
- * node.parentNode.insertBefore(newNode, node); //在node节点后面插入newNode
- * ```
- */
- insertBefore:function (target, source) {
- if (this.children) {
- if(target.parentNode){
- target.parentNode.removeChild(target);
- }
- for (var i = 0, ci; ci = this.children[i]; i++) {
- if (ci === source) {
- this.children.splice(i, 0, target);
- target.parentNode = this;
- return target;
- }
- }
-
- }
- },
-
- /**
- * 在传入节点的后面插入一个节点
- * @method insertAfter
- * @param { UE.uNode } target 要插入的节点
- * @param { UE.uNode } source 在该参数节点后面插入
- * @return { UE.uNode } 返回刚插入的子节点
- * @example
- * ```javascript
- * node.parentNode.insertAfter(newNode, node); //在node节点后面插入newNode
- * ```
- */
- insertAfter:function (target, source) {
- if (this.children) {
- if(target.parentNode){
- target.parentNode.removeChild(target);
- }
- for (var i = 0, ci; ci = this.children[i]; i++) {
- if (ci === source) {
- this.children.splice(i + 1, 0, target);
- target.parentNode = this;
- return target;
- }
-
- }
- }
- },
-
- /**
- * 从当前节点的子节点列表中,移除节点
- * @method removeChild
- * @param { UE.uNode } node 要移除的节点引用
- * @param { Boolean } keepChildren 是否保留移除节点的子节点,若传入true,自动把移除节点的子节点插入到移除的位置
- * @return { * } 返回刚移除的子节点
- * @example
- * ```javascript
- * node.removeChild(childNode,true); //在node的子节点列表中移除child节点,并且吧child的子节点插入到移除的位置
- * ```
- */
- removeChild:function (node,keepChildren) {
- if (this.children) {
- for (var i = 0, ci; ci = this.children[i]; i++) {
- if (ci === node) {
- this.children.splice(i, 1);
- ci.parentNode = null;
- if(keepChildren && ci.children && ci.children.length){
- for(var j= 0,cj;cj=ci.children[j];j++){
- this.children.splice(i+j,0,cj);
- cj.parentNode = this;
-
- }
- }
- return ci;
- }
- }
- }
- },
-
- /**
- * 获取当前节点所代表的元素属性,即获取attrs对象下的属性值
- * @method getAttr
- * @param { String } attrName 要获取的属性名称
- * @return { * } 返回attrs对象下的属性值
- * @example
- * ```javascript
- * node.getAttr('title');
- * ```
- */
- getAttr:function (attrName) {
- return this.attrs && this.attrs[attrName.toLowerCase()]
- },
-
- /**
- * 设置当前节点所代表的元素属性,即设置attrs对象下的属性值
- * @method setAttr
- * @param { String } attrName 要设置的属性名称
- * @param { * } attrVal 要设置的属性值,类型视设置的属性而定
- * @return { * } 返回attrs对象下的属性值
- * @example
- * ```javascript
- * node.setAttr('title','标题');
- * ```
- */
- setAttr:function (attrName, attrVal) {
- if (!attrName) {
- delete this.attrs;
- return;
- }
- if(!this.attrs){
- this.attrs = {};
- }
- if (utils.isObject(attrName)) {
- for (var a in attrName) {
- if (!attrName[a]) {
- delete this.attrs[a]
- } else {
- this.attrs[a.toLowerCase()] = attrName[a];
- }
- }
- } else {
- if (!attrVal) {
- delete this.attrs[attrName]
- } else {
- this.attrs[attrName.toLowerCase()] = attrVal;
- }
-
- }
- },
-
- /**
- * 获取当前节点在父节点下的位置索引
- * @method getIndex
- * @return { Number } 返回索引数值,如果没有父节点,返回-1
- * @example
- * ```javascript
- * node.getIndex();
- * ```
- */
- getIndex:function(){
- var parent = this.parentNode;
- for(var i= 0,ci;ci=parent.children[i];i++){
- if(ci === this){
- return i;
- }
- }
- return -1;
- },
-
- /**
- * 在当前节点下,根据id查找节点
- * @method getNodeById
- * @param { String } id 要查找的id
- * @return { UE.uNode } 返回找到的节点
- * @example
- * ```javascript
- * node.getNodeById('textId');
- * ```
- */
- getNodeById:function (id) {
- var node;
- if (this.children && this.children.length) {
- for (var i = 0, ci; ci = this.children[i++];) {
- if (node = getNodeById(ci, id)) {
- return node;
- }
- }
- }
- },
-
- /**
- * 在当前节点下,根据元素名称查找节点列表
- * @method getNodesByTagName
- * @param { String } tagNames 要查找的元素名称
- * @return { Array } 返回找到的节点列表
- * @example
- * ```javascript
- * node.getNodesByTagName('span');
- * ```
- */
- getNodesByTagName:function (tagNames) {
- tagNames = utils.trim(tagNames).replace(/[ ]{2,}/g, ' ').split(' ');
- var arr = [], me = this;
- utils.each(tagNames, function (tagName) {
- if (me.children && me.children.length) {
- for (var i = 0, ci; ci = me.children[i++];) {
- getNodesByTagName(ci, tagName, arr)
- }
- }
- });
- return arr;
- },
-
- /**
- * 根据样式名称,获取节点的样式值
- * @method getStyle
- * @param { String } name 要获取的样式名称
- * @return { String } 返回样式值
- * @example
- * ```javascript
- * node.getStyle('font-size');
- * ```
- */
- getStyle:function (name) {
- var cssStyle = this.getAttr('style');
- if (!cssStyle) {
- return ''
- }
- var reg = new RegExp('(^|;)\\s*' + name + ':([^;]+)','i');
- var match = cssStyle.match(reg);
- if (match && match[0]) {
- return match[2]
- }
- return '';
- },
-
- /**
- * 给节点设置样式
- * @method setStyle
- * @param { String } name 要设置的的样式名称
- * @param { String } val 要设置的的样值
- * @example
- * ```javascript
- * node.setStyle('font-size', '12px');
- * ```
- */
- setStyle:function (name, val) {
- function exec(name, val) {
- var reg = new RegExp('(^|;)\\s*' + name + ':([^;]+;?)', 'gi');
- cssStyle = cssStyle.replace(reg, '$1');
- if (val) {
- cssStyle = name + ':' + utils.unhtml(val) + ';' + cssStyle
- }
-
- }
-
- var cssStyle = this.getAttr('style');
- if (!cssStyle) {
- cssStyle = '';
- }
- if (utils.isObject(name)) {
- for (var a in name) {
- exec(a, name[a])
- }
- } else {
- exec(name, val)
- }
- this.setAttr('style', utils.trim(cssStyle))
- },
-
- /**
- * 传入一个函数,递归遍历当前节点下的所有节点
- * @method traversal
- * @param { Function } fn 遍历到节点的时,传入节点作为参数,运行此函数
- * @example
- * ```javascript
- * traversal(node, function(){
- * console.log(node.type);
- * });
- * ```
- */
- traversal:function(fn){
- if(this.children && this.children.length){
- nodeTraversal(this,fn);
- }
- return this;
- }
- }
-})();
-
-
-// core/htmlparser.js
-/**
- * html字符串转换成uNode节点
- * @file
- * @module UE
- * @since 1.2.6.1
- */
-
-/**
- * UEditor公用空间,UEditor所有的功能都挂载在该空间下
- * @unfile
- * @module UE
- */
-
-/**
- * html字符串转换成uNode节点的静态方法
- * @method htmlparser
- * @param { String } htmlstr 要转换的html代码
- * @param { Boolean } ignoreBlank 若设置为true,转换的时候忽略\n\r\t等空白字符
- * @return { uNode } 给定的html片段转换形成的uNode对象
- * @example
- * ```javascript
- * var root = UE.htmlparser('htmlparser
', true);
- * ```
- */
-
-var htmlparser = UE.htmlparser = function (htmlstr,ignoreBlank) {
- //todo 原来的方式 [^"'<>\/] 有\/就不能配对上 这样的标签了
- //先去掉了,加上的原因忘了,这里先记录
- var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\s\/<>]+)\s*((?:(?:"[^"]*")|(?:'[^']*')|[^"'<>])*)\/?>))/g,
- re_attr = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g;
-
- //ie下取得的html可能会有\n存在,要去掉,在处理replace(/[\t\r\n]*/g,'');代码高量的\n不能去除
- var allowEmptyTags = {
- b:1,code:1,i:1,u:1,strike:1,s:1,tt:1,strong:1,q:1,samp:1,em:1,span:1,
- sub:1,img:1,sup:1,font:1,big:1,small:1,iframe:1,a:1,br:1,pre:1
- };
- htmlstr = htmlstr.replace(new RegExp(domUtils.fillChar, 'g'), '');
- if(!ignoreBlank){
- htmlstr = htmlstr.replace(new RegExp('[\\r\\t\\n'+(ignoreBlank?'':' ')+']*<\/?(\\w+)\\s*(?:[^>]*)>[\\r\\t\\n'+(ignoreBlank?'':' ')+']*','g'), function(a,b){
- //br暂时单独处理
- if(b && allowEmptyTags[b.toLowerCase()]){
- return a.replace(/(^[\n\r]+)|([\n\r]+$)/g,'');
- }
- return a.replace(new RegExp('^[\\r\\n'+(ignoreBlank?'':' ')+']+'),'').replace(new RegExp('[\\r\\n'+(ignoreBlank?'':' ')+']+$'),'');
- });
- }
-
- var notTransAttrs = {
- 'href':1,
- 'src':1
- };
-
- var uNode = UE.uNode,
- needParentNode = {
- 'td':'tr',
- 'tr':['tbody','thead','tfoot'],
- 'tbody':'table',
- 'th':'tr',
- 'thead':'table',
- 'tfoot':'table',
- 'caption':'table',
- 'li':['ul', 'ol'],
- 'dt':'dl',
- 'dd':'dl',
- 'option':'select'
- },
- needChild = {
- 'ol':'li',
- 'ul':'li'
- };
-
- function text(parent, data) {
-
- if(needChild[parent.tagName]){
- var tmpNode = uNode.createElement(needChild[parent.tagName]);
- parent.appendChild(tmpNode);
- tmpNode.appendChild(uNode.createText(data));
- parent = tmpNode;
- }else{
-
- parent.appendChild(uNode.createText(data));
- }
- }
-
- function element(parent, tagName, htmlattr) {
- var needParentTag;
- if (needParentTag = needParentNode[tagName]) {
- var tmpParent = parent,hasParent;
- while(tmpParent.type != 'root'){
- if(utils.isArray(needParentTag) ? utils.indexOf(needParentTag, tmpParent.tagName) != -1 : needParentTag == tmpParent.tagName){
- parent = tmpParent;
- hasParent = true;
- break;
- }
- tmpParent = tmpParent.parentNode;
- }
- if(!hasParent){
- parent = element(parent, utils.isArray(needParentTag) ? needParentTag[0] : needParentTag)
- }
- }
- //按dtd处理嵌套
-// if(parent.type != 'root' && !dtd[parent.tagName][tagName])
-// parent = parent.parentNode;
- var elm = new uNode({
- parentNode:parent,
- type:'element',
- tagName:tagName.toLowerCase(),
- //是自闭合的处理一下
- children:dtd.$empty[tagName] ? null : []
- });
- //如果属性存在,处理属性
- if (htmlattr) {
- var attrs = {}, match;
- while (match = re_attr.exec(htmlattr)) {
- attrs[match[1].toLowerCase()] = notTransAttrs[match[1].toLowerCase()] ? (match[2] || match[3] || match[4]) : utils.unhtml(match[2] || match[3] || match[4])
- }
- elm.attrs = attrs;
- }
- //trace:3970
-// //如果parent下不能放elm
-// if(dtd.$inline[parent.tagName] && dtd.$block[elm.tagName] && !dtd[parent.tagName][elm.tagName]){
-// parent = parent.parentNode;
-// elm.parentNode = parent;
-// }
- parent.children.push(elm);
- //如果是自闭合节点返回父亲节点
- return dtd.$empty[tagName] ? parent : elm
- }
-
- function comment(parent, data) {
- parent.children.push(new uNode({
- type:'comment',
- data:data,
- parentNode:parent
- }));
- }
-
- var match, currentIndex = 0, nextIndex = 0;
- //设置根节点
- var root = new uNode({
- type:'root',
- children:[]
- });
- var currentParent = root;
-
- while (match = re_tag.exec(htmlstr)) {
- currentIndex = match.index;
- try{
- if (currentIndex > nextIndex) {
- //text node
- text(currentParent, htmlstr.slice(nextIndex, currentIndex));
- }
- if (match[3]) {
-
- if(dtd.$cdata[currentParent.tagName]){
- text(currentParent, match[0]);
- }else{
- //start tag
- currentParent = element(currentParent, match[3].toLowerCase(), match[4]);
- }
-
-
- } else if (match[1]) {
- if(currentParent.type != 'root'){
- if(dtd.$cdata[currentParent.tagName] && !dtd.$cdata[match[1]]){
- text(currentParent, match[0]);
- }else{
- var tmpParent = currentParent;
- while(currentParent.type == 'element' && currentParent.tagName != match[1].toLowerCase()){
- currentParent = currentParent.parentNode;
- if(currentParent.type == 'root'){
- currentParent = tmpParent;
- throw 'break'
- }
- }
- //end tag
- currentParent = currentParent.parentNode;
- }
-
- }
-
- } else if (match[2]) {
- //comment
- comment(currentParent, match[2])
- }
- }catch(e){}
-
- nextIndex = re_tag.lastIndex;
-
- }
- //如果结束是文本,就有可能丢掉,所以这里手动判断一下
- //例如 sdfsdfsdfsdfsdfsdfsdf
- if (nextIndex < htmlstr.length) {
- text(currentParent, htmlstr.slice(nextIndex));
- }
- return root;
-};
-
-
-// core/filternode.js
+}();
+
+// core/node.js
/**
- * UE过滤节点的静态方法
+ * 编辑器模拟的节点类
* @file
+ * @module UE
+ * @class uNode
+ * @since 1.2.6.1
*/
/**
* UEditor公用空间,UEditor所有的功能都挂载在该空间下
+ * @unfile
* @module UE
*/
+(function () {
-/**
- * 根据传入节点和过滤规则过滤相应节点
- * @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++;
- }
- }
- }
+ /**
+ * 编辑器模拟的节点类
+ * @unfile
+ * @module UE
+ * @class uNode
+ */
+ /**
+ * 通过一个键值对,创建一个uNode对象
+ * @constructor
+ * @param { Object } attr 传入要创建的uNode的初始属性
+ * @example
+ * ```javascript
+ * var node = new uNode({
+ * type:'element',
+ * tagName:'span',
+ * attrs:{style:'font-size:14px;'}
+ * }
+ * ```
+ */
+ var uNode = UE.uNode = function (obj) {
+ this.type = obj.type;
+ this.data = obj.data;
+ this.tagName = obj.tagName;
+ this.parentNode = obj.parentNode;
+ this.attrs = obj.attrs || {};
+ this.children = obj.children;
+ };
- }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;
- }
+ var notTransAttrs = {
+ 'href':1,
+ 'src':1,
+ '_src':1,
+ '_href':1,
+ 'cdata_data':1
+ };
- }
- 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++;
- }
- }
+ var notTransTagName = {
+ style:1,
+ script:1
+ };
+
+ var indentChar = ' ',
+ breakChar = '\n';
+
+ function insertLine(arr, current, begin) {
+ arr.push(breakChar);
+ return current + (begin ? 1 : -1);
+ }
+
+ function insertIndent(arr, current) {
+ //插入缩进
+ for (var i = 0; i < current; i++) {
+ arr.push(indentChar);
+ }
+ }
+
+ //创建uNode的静态方法
+ //支持标签和html
+ uNode.createElement = function (html) {
+ if (/[<>]/.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':
- node.parentNode.removeChild(node)
+ 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,' '))
}
}
- return function(root,rules){
- if(utils.isEmptyObject(rules)){
- return root;
+
+ 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(' ');
}
- var val;
- if(val = rules['-']){
- utils.each(val.split(' '),function(k){
- rules[k] = '-'
- })
+ 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)
+ }
+
}
- for(var i= 0,ci;ci=root.children[i];){
- filterNode(ci,rules);
- if(ci.parentNode){
- i++;
+ 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)
}
}
- return root;
+ 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 + '>');
+ }
+
}
-}();
-
-// core/plugin.js
-/**
- * Created with JetBrains PhpStorm.
- * User: campaign
- * Date: 10/8/13
- * Time: 6:15 PM
- * To change this template use File | Settings | File Templates.
- */
-UE.plugin = function(){
- var _plugins = {};
- return {
- register : function(pluginName,fn,oldOptionName,afterDisabled){
- if(oldOptionName && utils.isFunction(oldOptionName)){
- afterDisabled = oldOptionName;
- oldOptionName = null
- }
- _plugins[pluginName] = {
- optionName : oldOptionName || pluginName,
- execFn : fn,
- //当插件被禁用时执行
- afterDisabled : afterDisabled
- }
- },
- load : function(editor){
- utils.each(_plugins,function(plugin){
- var _export = plugin.execFn.call(editor);
- if(editor.options[plugin.optionName] !== false){
- if(_export){
- //后边需要再做扩展
- utils.each(_export,function(v,k){
- switch(k.toLowerCase()){
- case 'shortcutkey':
- editor.addshortcutkey(v);
- break;
- case 'bindevents':
- utils.each(v,function(fn,eventName){
- editor.addListener(eventName,fn);
- });
- break;
- case 'bindmultievents':
- utils.each(utils.isArray(v) ? v:[v],function(event){
- var types = utils.trim(event.type).split(/\s+/);
- utils.each(types,function(eventName){
- editor.addListener(eventName, event.handler);
- });
- });
- break;
- case 'commands':
- utils.each(v,function(execFn,execName){
- editor.commands[execName] = execFn
- });
- break;
- case 'outputrule':
- editor.addOutputRule(v);
- break;
- case 'inputrule':
- editor.addInputRule(v);
- break;
- case 'defaultoptions':
- editor.setOpt(v)
- }
- })
- }
-
- }else if(plugin.afterDisabled){
- plugin.afterDisabled.call(editor)
- }
-
- });
- //向下兼容
- utils.each(UE.plugins,function(plugin){
- plugin.call(editor);
- });
- },
- run : function(pluginName,editor){
- var plugin = _plugins[pluginName];
- if(plugin){
- plugin.exeFn.call(editor)
- }
- }
- }
-}();
-
-// core/keymap.js
-var keymap = UE.keymap = {
- 'Backspace' : 8,
- 'Tab' : 9,
- 'Enter' : 13,
-
- 'Shift':16,
- 'Control':17,
- 'Alt':18,
- 'CapsLock':20,
-
- 'Esc':27,
-
- 'Spacebar':32,
-
- 'PageUp':33,
- 'PageDown':34,
- 'End':35,
- 'Home':36,
-
- 'Left':37,
- 'Up':38,
- 'Right':39,
- 'Down':40,
-
- 'Insert':45,
-
- 'Del':46,
-
- 'NumLock':144,
-
- 'Cmd':91,
-
- '=':187,
- '-':189,
-
- "b":66,
- 'i':73,
- //回退
- 'z':90,
- 'y':89,
- //粘贴
- 'v' : 86,
- 'x' : 88,
-
- 's' : 83,
-
- 'n' : 78
-};
-
-// core/localstorage.js
-//存储媒介封装
-var LocalStorage = UE.LocalStorage = (function () {
-
- var storage = window.localStorage || getUserData() || null,
- LOCAL_FILE = 'localStorage';
-
- return {
-
- saveLocalData: function (key, data) {
-
- if (storage && data) {
- storage.setItem(key, data);
- return true;
- }
-
- return false;
-
- },
-
- getLocalData: function (key) {
-
- if (storage) {
- return storage.getItem(key);
- }
-
- return null;
-
- },
-
- removeItem: function (key) {
-
- storage && storage.removeItem(key);
-
- }
-
- };
-
- function getUserData() {
-
- var container = document.createElement("div");
- container.style.display = "none";
-
- if (!container.addBehavior) {
- return null;
- }
-
- container.addBehavior("#default#userdata");
-
- return {
-
- getItem: function (key) {
-
- var result = null;
-
- try {
- document.body.appendChild(container);
- container.load(LOCAL_FILE);
- result = container.getAttribute(key);
- document.body.removeChild(container);
- } catch (e) {
- }
-
- return result;
-
- },
-
- setItem: function (key, value) {
-
- document.body.appendChild(container);
- container.setAttribute(key, value);
- container.save(LOCAL_FILE);
- document.body.removeChild(container);
-
- },
-
- //// 暂时没有用到
- //clear: function () {
- //
- // var expiresTime = new Date();
- // expiresTime.setFullYear(expiresTime.getFullYear() - 1);
- // document.body.appendChild(container);
- // container.expires = expiresTime.toUTCString();
- // container.save(LOCAL_FILE);
- // document.body.removeChild(container);
- //
- //},
-
- removeItem: function (key) {
-
- document.body.appendChild(container);
- container.removeAttribute(key);
- container.save(LOCAL_FILE);
- document.body.removeChild(container);
-
- }
-
- };
-
- }
-
-})();
-
-(function () {
-
- var ROOTKEY = 'ueditor_preference';
-
- UE.Editor.prototype.setPreferences = function(key,value){
- var obj = {};
- if (utils.isString(key)) {
- obj[ key ] = value;
- } else {
- obj = key;
- }
- var data = LocalStorage.getLocalData(ROOTKEY);
- if (data && (data = utils.str2json(data))) {
- utils.extend(data, obj);
- } else {
- data = obj;
- }
- data && LocalStorage.saveLocalData(ROOTKEY, utils.json2str(data));
- };
-
- UE.Editor.prototype.getPreferences = function(key){
- var data = LocalStorage.getLocalData(ROOTKEY);
- if (data && (data = utils.str2json(data))) {
- return key ? data[key] : data
- }
- return null;
- };
-
- UE.Editor.prototype.removePreferences = function (key) {
- var data = LocalStorage.getLocalData(ROOTKEY);
- if (data && (data = utils.str2json(data))) {
- data[key] = undefined;
- delete data[key]
- }
- data && LocalStorage.saveLocalData(ROOTKEY, utils.json2str(data));
- };
-
-})();
-
-
-// plugins/defaultfilter.js
-///import core
-///plugin 编辑器默认的过滤转换机制
-UE.plugins['defaultfilter'] = function () {
- var me = this;
- me.setOpt({
- 'allowDivTransToP':true,
- 'disabledTableInTable':true
- });
- //默认的过滤处理
- //进入编辑器的内容处理
- me.addInputRule(function (root) {
- var allowDivTransToP = this.options.allowDivTransToP;
- var val;
- function tdParent(node){
- while(node && node.type == 'element'){
- if(node.tagName == 'td'){
- return true;
+ 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;
}
- 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)
+ }
+
+ 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)
}
- return;
+ if(ci.parentNode) i++
}
- 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);
-// }
- })
+ }else{
+ fn(root)
+ }
- });
+ }
+ uNode.prototype = {
- //从编辑器出去的内容处理
- me.addOutputRule(function (root) {
+ /**
+ * 当前节点对象,转换成html文本
+ * @method toHtml
+ * @return { String } 返回转换后的html字符串
+ * @example
+ * ```javascript
+ * node.toHtml();
+ * ```
+ */
- var val;
- root.traversal(function (node) {
- if (node.type == 'element') {
+ /**
+ * 当前节点对象,转换成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('')
+ },
- if (me.options.autoClearEmptyNode && dtd.$inline[node.tagName] && !dtd.$empty[node.tagName] && (!node.attrs || utils.isEmptyObject(node.attrs))) {
+ /**
+ * 获取节点的html内容
+ * @method innerHTML
+ * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点
+ * @return { String } 返回节点的html内容
+ * @example
+ * ```javascript
+ * var htmlstr = node.innerHTML();
+ * ```
+ */
- if (!node.firstChild()) node.parentNode.removeChild(node);
- else if (node.tagName == 'span' && (!node.attrs || utils.isEmptyObject(node.attrs))) {
- node.parentNode.removeChild(node, true)
+ /**
+ * 设置节点的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;
}
- return;
}
- switch (node.tagName) {
- case 'div':
- if (val = node.getAttr('cdata_tag')) {
- node.tagName = val;
- node.appendChild(UE.uNode.createText(node.getAttr('cdata_data')));
- node.setAttr({cdata_tag: '', cdata_data: '','_ue_custom_node_':''});
- }
- break;
- case 'a':
- if (val = node.getAttr('_href')) {
- node.setAttr({
- 'href': utils.html(val),
- '_href': ''
- })
- }
- break;
- break;
- case 'span':
- val = node.getAttr('id');
- if(val && /^_baidu_bookmark_/i.test(val)){
- node.parentNode.removeChild(node)
- }
- break;
- case 'img':
- if (val = node.getAttr('_src')) {
- node.setAttr({
- 'src': node.getAttr('_src'),
- '_src': ''
- })
- }
+ 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;
+ },
- });
-};
-
-
-// plugins/inserthtml.js
-/**
- * 插入html字符串插件
- * @file
- * @since 1.2.6.1
- */
+ /**
+ * 获取当前节点下的最后一个子节点
+ * @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;
+ },
-/**
- * 插入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)
+ /**
+ * 获取和当前节点有相同父亲节点的前一个节点
+ * @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];
+ }
}
- 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);
+
+ },
+
+ /**
+ * 获取和当前节点有相同父亲节点的后一个节点
+ * @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];
}
}
- 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)
+ },
+ /**
+ * 用新的节点替换当前节点
+ * @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;
}
}
}
- !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);
+ },
+
+ /**
+ * 在节点的子节点列表最后位置插入一个节点
+ * @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;
}
- domUtils.remove(child);
}
+ this.children.push(node);
+ node.parentNode = this;
+ return node;
}
- }
-
- 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;
+ },
+ /**
+ * 在传入节点的前面插入一个节点
+ * @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);
}
- 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;
+ for (var i = 0, ci; ci = this.children[i]; i++) {
+ if (ci === source) {
+ this.children.splice(i, 0, target);
+ target.parentNode = this;
+ return target;
}
}
- }
- 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
+ /**
+ * 在传入节点的后面插入一个节点
+ * @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;
}
+
}
- 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;
+ /**
+ * 从当前节点的子节点列表中,移除节点
+ * @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()]
+ },
- 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;
+ /**
+ * 设置当前节点所代表的元素属性,即设置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];
}
}
- var next = child.nextSibling;
- if(!div.firstChild && next && domUtils.isBlockElm(next)){
-
- range.setStart(next,0).collapse(true);
- break;
+ } else {
+ if (!attrVal) {
+ delete this.attrs[attrName]
+ } else {
+ this.attrs[attrName.toLowerCase()] = attrVal;
}
- 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]){
+ /**
+ * 获取当前节点在父节点下的位置索引
+ * @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;
+ },
- range.setStart(nextNode,0).collapse(true).shrinkBoundary()
+ /**
+ * 在当前节点下,根据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;
}
- }else{
+ }
+ }
+ },
- try{
- child.innerHTML = browser.ie ? domUtils.fillChar : ' ';
- }catch(e){
- range.setStartBefore(child);
- domUtils.remove(child)
+ /**
+ * 在当前节点下,根据元素名称查找节点列表
+ * @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 ''
}
- //加上true因为在删除表情等时会删两次,第一次是删的fillData
- try{
- range.select(true);
- }catch(e){}
+ 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))
+ },
- setTimeout(function(){
- range = me.selection.getRange();
- range.scrollToView(me.autoHeightEnabled,me.autoHeightEnabled ? domUtils.getXY(me.iframe).y:0);
- me.fireEvent('afterinserthtml', html);
- },200);
+ /**
+ * 传入一个函数,递归遍历当前节点下的所有节点
+ * @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;
+ }
}
-};
-
-
-// plugins/autotypeset.js
+})();
+
+
+// core/htmlparser.js
/**
- * 自动排版
+ * html字符串转换成uNode节点
* @file
+ * @module UE
* @since 1.2.6.1
*/
/**
- * 对当前编辑器的内容执行自动排版, 排版的行为根据config配置文件里的“autotypeset”选项进行控制。
- * @command autotypeset
- * @method execCommand
- * @param { String } cmd 命令字符串
+ * 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
- * editor.execCommand( 'autotypeset' );
+ * var root = UE.htmlparser('htmlparser ', true);
* ```
*/
-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 htmlparser = UE.htmlparser = function (htmlstr,ignoreBlank) {
+ //todo 原来的方式 [^"'<>\/] 有\/就不能配对上 这样的标签了
+ //先去掉了,加上的原因忘了,这里先记录
+ var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\s\/<>]+)\s*((?:(?:"[^"]*")|(?:'[^']*')|[^"'<>])*)\/?>))/g,
+ re_attr = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g;
- 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;
+ //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?'':' ')+']+$'),'');
+ });
}
- readLocalOpts();
+ var notTransAttrs = {
+ 'href':1,
+ 'src':1
+ };
- 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;
- }
+ 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'
+ };
- return notEmpty ? !domUtils.isEmptyBlock(node) : domUtils.isEmptyBlock(node,new RegExp('[\\s'+domUtils.fillChar
- +']','g'));
+ 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 removeNotAttributeSpan(node){
- if(!node.style.cssText){
- domUtils.removeAttributes(node,['style']);
- if(node.tagName.toLowerCase() == 'span' && domUtils.hasNoAttributes(node)){
- domUtils.remove(node,true);
+ 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 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,'*');
+ function comment(parent, data) {
+ parent.children.push(new uNode({
+ type:'comment',
+ data:data,
+ parentNode:parent
+ }));
+ }
- // 行首缩进,段落方向,段间距,段内间距
- for(var i=0,ci;ci=nodes[i++];){
+ var match, currentIndex = 0, nextIndex = 0;
+ //设置根节点
+ var root = new uNode({
+ type:'root',
+ children:[]
+ });
+ var currentParent = root;
- if(me.fireEvent('excludeNodeinautotype',ci) === true){
- continue;
+ while (match = re_tag.exec(htmlstr)) {
+ currentIndex = match.index;
+ try{
+ if (currentIndex > nextIndex) {
+ //text node
+ text(currentParent, htmlstr.slice(nextIndex, currentIndex));
}
- //font-size
- if(opt.clearFontSize && ci.style.fontSize){
- domUtils.removeStyle(ci,'font-size');
+ if (match[3]) {
- removeNotAttributeSpan(ci);
-
- }
- //font-family
- if(opt.clearFontFamily && ci.style.fontFamily){
- domUtils.removeStyle(ci,'font-family');
- removeNotAttributeSpan(ci);
- }
+ if(dtd.$cdata[currentParent.tagName]){
+ text(currentParent, match[0]);
+ }else{
+ //start tag
+ currentParent = element(currentParent, match[3].toLowerCase(), match[4]);
+ }
- 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;
+ } 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;
}
- domUtils.remove(ci);
- continue;
}
+ } else if (match[2]) {
+ //comment
+ comment(currentParent, match[2])
}
- 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';
+ }catch(e){}
- }
+ nextIndex = re_tag.lastIndex;
- //去掉class,保留的class不去掉
- if(opt.removeClass && ci.className && !remainClass[ci.className.toLowerCase()]){
+ }
+ //如果结束是文本,就有可能丢掉,所以这里手动判断一下
+ //例如 sdfsdfsdfsdfsdfsdfsdf
+ if (nextIndex < htmlstr.length) {
+ text(currentParent, htmlstr.slice(nextIndex));
+ }
+ return root;
+};
- 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','');
- }
+// 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++;
+ }
+ }
+ }
- }
- 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 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++;
}
-
-
+ }
}
- } 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()
+ break;
+ case 'comment':
+ node.parentNode.removeChild(node)
}
- 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()
+
+ }
+ return function(root,rules){
+ if(utils.isEmptyObject(rules)){
+ return root;
}
- if(html){
- html.html = cont.innerHTML;
+ var val;
+ if(val = rules['-']){
+ utils.each(val.split(' '),function(k){
+ rules[k] = '-'
+ })
}
- }
- 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);
+ for(var i= 0,ci;ci=root.children[i];){
+ filterNode(ci,rules);
+ if(ci.parentNode){
+ i++;
}
}
- return result;
+ return root;
}
- 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);
+}();
+
+// 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)
}
}
- return tmp;
}
+}();
- function readLocalOpts() {
- var cookieOpt = me.getPreferences('autotypeset');
- utils.extend(me.options.autotypeset, cookieOpt);
- }
+// core/keymap.js
+var keymap = UE.keymap = {
+ 'Backspace' : 8,
+ 'Tab' : 9,
+ 'Enter' : 13,
- me.commands['autotypeset'] = {
- execCommand:function () {
- me.removeListener('beforepaste',autotype);
- if(opt.pasteFilter){
- me.addListener('beforepaste',autotype);
- }
- autotype.call(me)
- }
+ 'Shift':16,
+ 'Control':17,
+ 'Alt':18,
+ 'CapsLock':20,
- };
+ 'Esc':27,
-};
+ 'Spacebar':32,
-
-
-// plugins/autosubmit.js
-/**
- * 快捷键提交
- * @file
- * @since 1.2.6.1
- */
+ 'PageUp':33,
+ 'PageDown':34,
+ 'End':35,
+ 'Home':36,
-/**
- * 提交表单
- * @command autosubmit
- * @method execCommand
- * @param { String } cmd 命令字符串
- * @example
- * ```javascript
- * editor.execCommand( 'autosubmit' );
- * ```
- */
+ 'Left':37,
+ 'Up':38,
+ 'Right':39,
+ 'Down':40,
-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');
+ 'Insert':45,
- 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;
- }
+ 'Del':46,
- 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方法
+ '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';
- var orgFn = me.hasContents;
- me.hasContents = function(){
- if(me.queryCommandValue('background')){
- return true
- }
- return orgFn.apply(me,arguments);
- };
return {
- bindEvents: {
- 'getAllHtml': function (type, headHtml) {
- var body = this.body,
- su = domUtils.getComputedStyle(body, "background-image"),
- url = "";
- if (su.indexOf(me.options.imagePath) > 0) {
- url = su.substring(su.indexOf(me.options.imagePath), su.length - 1).replace(/"|\(|\)/ig, "");
- } else {
- url = su != "none" ? su.replace(/url\("?|"?\)/ig, "") : "";
- }
- var html = ' ';
- headHtml.push(html);
- },
- 'aftersetcontent': function () {
- if(isSetColored == false) setBackground();
- }
- },
- inputRule: function (root) {
- isSetColored = false;
- utils.each(root.getNodesByTagName('p'), function (p) {
- var styles = p.getAttr('data-background');
- if (styles) {
- isSetColored = true;
- setBackground(stringToObj(styles));
- p.parentNode.removeChild(p);
- }
- })
- },
- outputRule: function (root) {
- var me = this,
- styles = (utils.cssRule(cssRuleId, me.document) || '').replace(/[\n\r]+/g, '').match(reg);
- if (styles) {
- root.appendChild(UE.uNode.createElement('
'));
- }
- },
- commands: {
- 'background': {
- execCommand: function (cmd, obj) {
- setBackground(obj);
- },
- queryCommandValue: function () {
- var me = this,
- styles = (utils.cssRule(cssRuleId, me.document) || '').replace(/[\n\r]+/g, '').match(reg);
- return styles ? stringToObj(styles[1]) : null;
- },
- notNeedUndo: true
+
+ saveLocalData: function (key, data) {
+
+ if (storage && data) {
+ storage.setItem(key, data);
+ return true;
}
- }
- }
-});
-
-// plugins/image.js
-/**
- * 图片插入、排版插件
- * @file
- * @since 1.2.6.1
- */
-
-/**
- * 图片对齐方式
- * @command imagefloat
- * @method execCommand
- * @remind 值center为独占一行居中
- * @param { String } cmd 命令字符串
- * @param { String } align 对齐方式,可传left、right、none、center
- * @remaind center表示图片独占一行
- * @example
- * ```javascript
- * editor.execCommand( 'imagefloat', 'center' );
- * ```
- */
-
-/**
- * 如果选区所在位置是图片区域
- * @command imagefloat
- * @method queryCommandValue
- * @param { String } cmd 命令字符串
- * @return { String } 返回图片对齐方式
- * @example
- * ```javascript
- * editor.queryCommandValue( 'imagefloat' );
- * ```
- */
-
-UE.commands['imagefloat'] = {
- execCommand:function (cmd, align) {
- var me = this,
- range = me.selection.getRange();
- if (!range.collapsed) {
- var img = range.getClosedNode();
- if (img && img.tagName == 'IMG') {
- switch (align) {
- case 'left':
- case 'right':
- case 'none':
- var pN = img.parentNode, tmpNode, pre, next;
- while (dtd.$inline[pN.tagName] || pN.tagName == 'A') {
- pN = pN.parentNode;
- }
- tmpNode = pN;
- if (tmpNode.tagName == 'P' && domUtils.getStyle(tmpNode, 'text-align') == 'center') {
- if (!domUtils.isBody(tmpNode) && domUtils.getChildCount(tmpNode, function (node) {
- return !domUtils.isBr(node) && !domUtils.isWhitespace(node);
- }) == 1) {
- pre = tmpNode.previousSibling;
- next = tmpNode.nextSibling;
- if (pre && next && pre.nodeType == 1 && next.nodeType == 1 && pre.tagName == next.tagName && domUtils.isBlockElm(pre)) {
- pre.appendChild(tmpNode.firstChild);
- while (next.firstChild) {
- pre.appendChild(next.firstChild);
- }
- domUtils.remove(tmpNode);
- domUtils.remove(next);
- } else {
- domUtils.setStyle(tmpNode, 'text-align', '');
- }
-
-
- }
-
- range.selectNode(img).select();
- }
- domUtils.setStyle(img, 'float', align == 'none' ? '' : align);
- if(align == 'none'){
- domUtils.removeAttributes(img,'align');
- }
-
- break;
- case 'center':
- if (me.queryCommandValue('imagefloat') != 'center') {
- pN = img.parentNode;
- domUtils.setStyle(img, 'float', '');
- domUtils.removeAttributes(img,'align');
- tmpNode = img;
- while (pN && domUtils.getChildCount(pN, function (node) {
- return !domUtils.isBr(node) && !domUtils.isWhitespace(node);
- }) == 1
- && (dtd.$inline[pN.tagName] || pN.tagName == 'A')) {
- tmpNode = pN;
- pN = pN.parentNode;
- }
- range.setStartBefore(tmpNode).setCursor(false);
- pN = me.document.createElement('div');
- pN.appendChild(tmpNode);
- domUtils.setStyle(tmpNode, 'float', '');
-
- me.execCommand('insertHtml', '' + pN.innerHTML + ' ');
-
- tmpNode = me.document.getElementById('_img_parent_tmp');
- tmpNode.removeAttribute('id');
- tmpNode = tmpNode.firstChild;
- range.selectNode(tmpNode).select();
- //去掉后边多余的元素
- next = tmpNode.parentNode.nextSibling;
- if (next && domUtils.isEmptyNode(next)) {
- domUtils.remove(next);
- }
-
- }
-
- break;
- }
-
- }
- }
- },
- queryCommandValue:function () {
- var range = this.selection.getRange(),
- startNode, floatStyle;
- if (range.collapsed) {
- return 'none';
- }
- startNode = range.getClosedNode();
- if (startNode && startNode.nodeType == 1 && startNode.tagName == 'IMG') {
- floatStyle = domUtils.getComputedStyle(startNode, 'float') || startNode.getAttribute('align');
-
- if (floatStyle == 'none') {
- floatStyle = domUtils.getComputedStyle(startNode.parentNode, 'text-align') == 'center' ? 'center' : floatStyle;
- }
- return {
- left:1,
- right:1,
- center:1
- }[floatStyle] ? floatStyle : 'none';
- }
- return 'none';
-
-
- },
- queryCommandState:function () {
- var range = this.selection.getRange(),
- startNode;
-
- if (range.collapsed) return -1;
-
- startNode = range.getClosedNode();
- if (startNode && startNode.nodeType == 1 && startNode.tagName == 'IMG') {
- return 0;
- }
- return -1;
- }
-};
-
-
-/**
- * 插入图片
- * @command insertimage
- * @method execCommand
- * @param { String } cmd 命令字符串
- * @param { Object } opt 属性键值对,这些属性都将被复制到当前插入图片
- * @remind 该命令第二个参数可接受一个图片配置项对象的数组,可以插入多张图片,
- * 此时数组的每一个元素都是一个Object类型的图片属性集合。
- * @example
- * ```javascript
- * editor.execCommand( 'insertimage', {
- * src:'a/b/c.jpg',
- * width:'100',
- * height:'100'
- * } );
- * ```
- * @example
- * ```javascript
- * editor.execCommand( 'insertimage', [{
- * src:'a/b/c.jpg',
- * width:'100',
- * height:'100'
- * },{
- * src:'a/b/d.jpg',
- * width:'100',
- * height:'100'
- * }] );
- * ```
- */
-
-UE.commands['insertimage'] = {
- execCommand:function (cmd, opt) {
-
- opt = utils.isArray(opt) ? opt : [opt];
- if (!opt.length) {
- return;
- }
- var me = this,
- range = me.selection.getRange(),
- img = range.getClosedNode();
-
- if(me.fireEvent('beforeinsertimage', opt) === true){
- return;
- }
-
- function unhtmlData(imgCi) {
-
- utils.each('width,height,border,hspace,vspace'.split(','), function (item) {
-
- if (imgCi[item]) {
- imgCi[item] = parseInt(imgCi[item], 10) || 0;
- }
- });
-
- utils.each('src,_src'.split(','), function (item) {
-
- if (imgCi[item]) {
- imgCi[item] = utils.unhtmlForUrl(imgCi[item]);
- }
- });
- utils.each('title,alt'.split(','), function (item) {
-
- if (imgCi[item]) {
- imgCi[item] = utils.unhtml(imgCi[item]);
- }
- });
- }
-
- if (img && /img/i.test(img.tagName) && (img.className != "edui-faked-video" || img.className.indexOf("edui-upload-video")!=-1) && !img.getAttribute("word_img")) {
- var first = opt.shift();
- var floatStyle = first['floatStyle'];
- delete first['floatStyle'];
-//// img.style.border = (first.border||0) +"px solid #000";
-//// img.style.margin = (first.margin||0) +"px";
-// img.style.cssText += ';margin:' + (first.margin||0) +"px;" + 'border:' + (first.border||0) +"px solid #000";
- domUtils.setAttributes(img, first);
- me.execCommand('imagefloat', floatStyle);
- if (opt.length > 0) {
- range.setStartAfter(img).setCursor(false, true);
- me.execCommand('insertimage', opt);
- }
-
- } else {
- var html = [], str = '', ci;
- ci = opt[0];
- if (opt.length == 1) {
- unhtmlData(ci);
-
- str = ' ';
- if (ci['floatStyle'] == 'center') {
- str = '' + str + ' ';
- }
- html.push(str);
-
- } else {
- for (var i = 0; ci = opt[i++];) {
- unhtmlData(ci);
- str = ' ';
- html.push(str);
- }
- }
-
- me.execCommand('insertHtml', html.join(''));
- }
-
- me.fireEvent('afterinsertimage', opt)
- }
-};
-
-
-// plugins/justify.js
-/**
- * 段落格式
- * @file
- * @since 1.2.6.1
- */
-/**
- * 段落对齐方式
- * @command justify
- * @method execCommand
- * @param { String } cmd 命令字符串
- * @param { String } align 对齐方式:left => 居左,right => 居右,center => 居中,justify => 两端对齐
- * @example
- * ```javascript
- * editor.execCommand( 'justify', 'center' );
- * ```
- */
-/**
- * 如果选区所在位置是段落区域,返回当前段落对齐方式
- * @command justify
- * @method queryCommandValue
- * @param { String } cmd 命令字符串
- * @return { String } 返回段落对齐方式
- * @example
- * ```javascript
- * editor.queryCommandValue( 'justify' );
- * ```
- */
+ return false;
-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;
+ getLocalData: function (key) {
- //闭合时单独处理
- if (range.collapsed) {
- txt = this.document.createTextNode('p');
- range.insertNode(txt);
- }
- doJustify(range, align);
- if (txt) {
- range.setStartBefore(txt).collapse(true);
- domUtils.remove(txt);
+ if (storage) {
+ return storage.getItem(key);
}
- range.select();
-
+ return null;
- 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;
+ removeItem: function (key) {
+
+ storage && storage.removeItem(key);
+
}
};
-};
-
-
-// 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' );
- * ```
- */
+ function getUserData() {
-/**
- * 字体背景颜色
- * @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' );
- * ```
- */
+ var container = document.createElement("div");
+ container.style.display = "none";
-/**
- * 字体大小
- * @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' );
- * ```
- */
+ if (!container.addBehavior) {
+ return null;
+ }
-/**
- * 字体样式
- * @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' );
- * ```
- */
+ container.addBehavior("#default#userdata");
-/**
- * 字体下划线,与删除线互斥
- * @command underline
- * @method execCommand
- * @param { String } cmd 命令字符串
- * @example
- * ```javascript
- * editor.execCommand( 'underline' );
- * ```
- */
+ return {
-/**
- * 字体删除线,与下划线互斥
- * @command strikethrough
- * @method execCommand
- * @param { String } cmd 命令字符串
- * @example
- * ```javascript
- * editor.execCommand( 'strikethrough' );
- * ```
- */
+ getItem: function (key) {
-/**
- * 字体边框
- * @command fontborder
- * @method execCommand
- * @param { String } cmd 命令字符串
- * @example
- * ```javascript
- * editor.execCommand( 'fontborder' );
- * ```
- */
+ var result = null;
-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'
+ try {
+ document.body.appendChild(container);
+ container.load(LOCAL_FILE);
+ result = container.getAttribute(key);
+ document.body.removeChild(container);
+ } catch (e) {
+ }
- };
- 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]
- });
+ return result;
- 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;
- }
- }
+ setItem: function (key, value) {
- }
- function mergeChild(rng,cmdName,value){
- if(needSetChild[cmdName]){
- rng.adjustmentBoundary();
- if(!rng.collapsed && rng.startContainer.nodeType == 1){
- var start = rng.startContainer.childNodes[rng.startOffset];
- if(start && domUtils.isTagNode(start,'span')){
- var bk = rng.createBookmark();
- utils.each(domUtils.getElementsByTagName(start, 'span'), function (span) {
- if (!span.parentNode || domUtils.isBookmarkNode(span))return;
- if(cmdName == 'backcolor' && domUtils.getComputedStyle(span,'background-color').toLowerCase() === value){
- return;
- }
- domUtils.removeStyle(span,needSetChild[cmdName]);
- if(span.style.cssText.replace(/^\s+$/,'').length == 0){
- domUtils.remove(span,true)
- }
- });
- rng.moveToBookmark(bk)
- }
- }
- }
+ document.body.appendChild(container);
+ container.setAttribute(key, value);
+ container.save(LOCAL_FILE);
+ document.body.removeChild(container);
- }
- 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;
- }
- }
+ },
+ //// 暂时没有用到
+ //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);
- 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();
+(function () {
+ var ROOTKEY = 'ueditor_preference';
- } else {
- range.insertNode(text);
- range.selectNode(text).select();
- span = range.document.createElement('span');
+ 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));
+ };
- if (needCmd[cmd]) {
- //a标签内的不处理跳过
- if (domUtils.findParentByTagName(text, 'a', true)) {
- range.setStartBefore(text).setCursor();
- domUtils.remove(text);
- return;
- }
- me.execCommand('removeFormat', 'span,a', style);
- }
+ UE.Editor.prototype.getPreferences = function(key){
+ var data = LocalStorage.getLocalData(ROOTKEY);
+ if (data && (data = utils.str2json(data))) {
+ return key ? data[key] : data
+ }
+ return null;
+ };
- span.style.cssText = style + ':' + value;
+ 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));
+ };
+})();
- 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;
- }
- }
+// plugins/defaultfilter.js
+///import core
+///plugin 编辑器默认的过滤转换机制
- 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();
+UE.plugins['defaultfilter'] = function () {
+ var me = this;
+ me.setOpt({
+ 'allowDivTransToP':true,
+ 'disabledTableInTable':true
+ });
+ //默认的过滤处理
+ //进入编辑器的内容处理
+ me.addInputRule(function (root) {
+ var allowDivTransToP = this.options.allowDivTransToP;
+ var val;
+ function tdParent(node){
+ while(node && node.type == 'element'){
+ if(node.tagName == 'td'){
+ return true;
+ }
+ node = node.parentNode;
+ }
+ return false;
+ }
+ //进行默认的处理
+ root.traversal(function (node) {
+ if (node.type == 'element') {
+ if (!dtd.$cdata[node.tagName] && me.options.autoClearEmptyNode && dtd.$inline[node.tagName] && !dtd.$empty[node.tagName] && (!node.attrs || utils.isEmptyObject(node.attrs))) {
+ if (!node.firstChild()) node.parentNode.removeChild(node);
+ else if (node.tagName == 'span' && (!node.attrs || utils.isEmptyObject(node.attrs))) {
+ node.parentNode.removeChild(node, true)
+ }
+ return;
+ }
+ switch (node.tagName) {
+ case 'style':
+ case 'script':
+ node.setAttr({
+ cdata_tag: node.tagName,
+ cdata_data: (node.innerHTML() || ''),
+ '_ue_custom_node_':'true'
+ });
+ node.tagName = 'div';
+ node.innerHTML('');
+ break;
+ case 'a':
+ if (val = node.getAttr('href')) {
+ node.setAttr('_href', val)
+ }
+ break;
+ case 'img':
+ //todo base64暂时去掉,后边做远程图片上传后,干掉这个
+ if (val = node.getAttr('src')) {
+ if (/^data:/.test(val)) {
+ node.parentNode.removeChild(node);
+ break;
+ }
+ }
+ node.setAttr('_src', node.getAttr('src'));
+ break;
+ case 'span':
+ if (browser.webkit && (val = node.getStyle('white-space'))) {
+ if (/nowrap|normal/.test(val)) {
+ node.setStyle('white-space', '');
+ if (me.options.autoClearEmptyNode && utils.isEmptyObject(node.attrs)) {
+ node.parentNode.removeChild(node, true)
}
-
- //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;
+ 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;
}
-
- tmpNode = tmpNode.parentNode;
+ });
+ if (!node.firstChild()) {
+ node.innerHTML(browser.ie ? ' ' : ' ')
}
- 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;
+ 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);
}
}
- tmp = tmp.parentNode;
}
- return ''
- }
+ 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( cmdName == 'FontSize' ) {
- var styleVal = domUtils.getComputedStyle(startNode, style),
- tmp = /^([\d\.]+)(\w+)$/.exec( styleVal );
+ }
+// if(node.type == 'comment'){
+// node.parentNode.removeChild(node);
+// }
+ })
- if( tmp ) {
+ });
- return Math.floor( tmp[1] ) + tmp[2];
+ //从编辑器出去的内容处理
+ me.addOutputRule(function (root) {
- }
+ var val;
+ root.traversal(function (node) {
+ if (node.type == 'element') {
- return styleVal;
+ if (me.options.autoClearEmptyNode && dtd.$inline[node.tagName] && !dtd.$empty[node.tagName] && (!node.attrs || utils.isEmptyObject(node.attrs))) {
+ if (!node.firstChild()) node.parentNode.removeChild(node);
+ else if (node.tagName == 'span' && (!node.attrs || utils.isEmptyObject(node.attrs))) {
+ node.parentNode.removeChild(node, true)
}
+ return;
+ }
+ switch (node.tagName) {
+ case 'div':
+ if (val = node.getAttr('cdata_tag')) {
+ node.tagName = val;
+ node.appendChild(UE.uNode.createText(node.getAttr('cdata_data')));
+ node.setAttr({cdata_tag: '', cdata_data: '','_ue_custom_node_':''});
+ }
+ break;
+ case 'a':
+ if (val = node.getAttr('_href')) {
+ node.setAttr({
+ 'href': utils.html(val),
+ '_href': ''
+ })
+ }
+ break;
+ break;
+ case 'span':
+ val = node.getAttr('id');
+ if(val && /^_baidu_bookmark_/i.test(val)){
+ node.parentNode.removeChild(node)
+ }
+ break;
+ case 'img':
+ if (val = node.getAttr('_src')) {
+ node.setAttr({
+ 'src': node.getAttr('_src'),
+ '_src': ''
+ })
+ }
- 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
+ }
+
+ })
+
+
+ });
+};
+
+
+// plugins/inserthtml.js
/**
- * 超链接
+ * 插入html字符串插件
* @file
* @since 1.2.6.1
*/
/**
- * 插入超链接
- * @command link
- * @method execCommand
- * @param { String } cmd 命令字符串
- * @param { Object } options 设置自定义属性,例如:url、title、target
- * @example
- * ```javascript
- * editor.execCommand( 'link', '{
- * url:'ueditor.baidu.com',
- * title:'ueditor',
- * target:'_blank'
- * }' );
- * ```
- */
-/**
- * 返回当前选中的第一个超链接节点
- * @command link
- * @method queryCommandValue
- * @param { String } cmd 命令字符串
- * @return { Element } 超链接节点
- * @example
- * ```javascript
- * editor.queryCommandValue( 'link' );
- * ```
- */
-
-/**
- * 取消超链接
- * @command unlink
+ * 插入html代码
+ * @command inserthtml
* @method execCommand
* @param { String } cmd 命令字符串
+ * @param { String } html 插入的html字符串
+ * @remaind 插入的标签内容是在当前的选区位置上插入,如果当前是闭合状态,那直接插入内容, 如果当前是选中状态,将先清除当前选中内容后,再做插入
+ * @warning 注意:该命令会对当前选区的位置,对插入的内容进行过滤转换处理。 过滤的规则遵循html语意化的原则。
* @example
* ```javascript
- * editor.execCommand( 'unlink');
+ * //xxx[BB]xxx 当前选区为非闭合选区,选中BB这两个文本
+ * //执行命令,插入CC
+ * //插入后的效果 xxxCCxxx
+ * //xx|xxx 当前选区为闭合状态
+ * //插入CC
+ * //结果 xx CC xxx
+ * //xxxx |xxx 当前选区在两个p标签之间
+ * //插入 xxxx
+ * //结果 xxxx xxxx xxx
* ```
*/
-UE.plugins['link'] = function(){
- function optimize( range ) {
- var start = range.startContainer,end = range.endContainer;
-
- if ( start = domUtils.findParentByTagName( start, 'a', true ) ) {
- range.setStartBefore( start );
+UE.commands['inserthtml'] = {
+ execCommand: function (command,html,notNeedFilter){
+ var me = this,
+ range,
+ div;
+ if(!html){
+ return;
}
- if ( end = domUtils.findParentByTagName( end, 'a', true ) ) {
- range.setEndAfter( end );
+ if(me.fireEvent('beforeinserthtml',html) === true){
+ return;
}
- }
-
-
- UE.commands['unlink'] = {
- execCommand : function() {
- var range = this.selection.getRange(),
- bookmark;
- if(range.collapsed && !domUtils.findParentByTagName( range.startContainer, 'a', 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);
}
- bookmark = range.createBookmark();
- optimize( range );
- range.removeInlineStyle( 'a' ).moveToBookmark( bookmark ).select();
- },
- queryCommandState : function(){
- return !this.highlight && this.queryCommandValue('link') ? 0 : -1;
+ //执行默认的处理
+ 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)
- };
- 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();
+ !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);
+ }
+ }
+
}
- 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);
+ 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;
+ }
+ }
}
- domUtils.setAttributes( a, opt );
- start = domUtils.findParentByTagName( rngClone.startContainer, 'a', true );
- if(start && domUtils.isInNodeEndBoundary(rngClone,start)){
- range.setStartAfter(start).collapse(true);
+ li = domUtils.findParentByTagName(range.startContainer,'li',true);
+ if(domUtils.isEmptyBlock(li)){
+ domUtils.remove(li)
+ }
+ if(last){
+ range.setStartAfter(last).collapse(true).select(true)
}
- a[browser.ie ? 'innerText' : 'textContent'] = text;
- range.insertNode(a).selectNode( a );
- } else {
- range.applyInlineStyle( 'a', opt );
+ }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){
- }
- }
- 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);
+ child = p
+ }
+ }
+ range.insertNode( child );
+ nextNode = child.nextSibling;
+ if ( !hadBreak && child.nodeType == domUtils.NODE_ELEMENT && domUtils.isBlockElm( child ) ){
- },
- 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;
+ 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;
- 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;
+ 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占位
- 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;
+ if(!browser.ie &&
+ (next = child.nextSibling) &&
+ domUtils.isBlockElm(next) &&
+ next.lastChild &&
+ !domUtils.isBr(next.lastChild)){
+ next.appendChild(me.document.createElement('br'));
}
+ hadBreak = 1;
}
}
- return node;
+ var next = child.nextSibling;
+ if(!div.firstChild && next && domUtils.isBlockElm(next)){
+
+ range.setStart(next,0).collapse(true);
+ break;
+ }
+ range.setEndAfter( child ).collapse();
+
}
- },
- 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;
+ 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/removeformat.js
+
+
+// plugins/autotypeset.js
/**
- * 清除格式
+ * 自动排版
* @file
* @since 1.2.6.1
*/
/**
- * 清除文字样式
- * @command removeformat
+ * 对当前编辑器的内容执行自动排版, 排版的行为根据config配置文件里的“autotypeset”选项进行控制。
+ * @command autotypeset
* @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' );
+ * editor.execCommand( 'autotypeset' );
* ```
*/
-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 ) {
+UE.plugins['autotypeset'] = function(){
- 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;
- };
+ 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
+ }});
- function isRedundantSpan (node) {
- if (node.nodeType == 3 || node.tagName.toLowerCase() != 'span'){
- return 0;
- }
- if (browser.ie) {
- //ie 下判断实效,所以只能简单用style来判断
- //return node.style.cssText == '' ? 1 : 0;
- var attrs = node.attributes;
- if ( attrs.length ) {
- for ( var i = 0,l = attrs.length; i
- var node = range.startContainer,
- tmp,
- collapsed = range.collapsed;
- while(node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]){
- tmp = node.parentNode;
- range.setStartBefore(node);
- //trace:937
- //更新结束边界
- if(range.startContainer === range.endContainer){
- range.endOffset--;
- }
- domUtils.remove(node);
- node = tmp;
+ // if(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(!collapsed){
- node = range.endContainer;
- while(node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]){
- tmp = node.parentNode;
- range.setEndBefore(node);
- domUtils.remove(node);
+ //表情不处理
+ 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','');
+ }
- node = tmp;
- }
+
+ }
+
+
+ }
+ 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;
+ }
- range = this.selection.getRange();
- doRemove( range );
- range.select();
+ 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/blockquote.js
+
+
+
+// plugins/autosubmit.js
/**
- * 添加引用
+ * 快捷键提交
* @file
* @since 1.2.6.1
*/
/**
- * 添加引用
- * @command blockquote
+ * 提交表单
+ * @command autosubmit
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
- * editor.execCommand( 'blockquote' );
+ * 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
/**
- * 添加引用
- * @command blockquote
- * @method execCommand
- * @param { String } cmd 命令字符串
- * @param { Object } attrs 节点属性
- * @example
- * ```javascript
- * editor.execCommand( 'blockquote',{
- * style: "color: red;"
- * } );
- * ```
+ * 背景插件,为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');
-
-UE.plugins['blockquote'] = function(){
- var me = this;
- function getObj(editor){
- return domUtils.filterNodeList(editor.selection.getStartElementPath(),'blockquote');
+ 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;
}
- me.commands['blockquote'] = {
- execCommand : function( cmdName, attrs ) {
- var range = this.selection.getRange(),
- obj = getObj(this),
- blockquote = dtd.blockquote,
- bookmark = range.createBookmark();
- if ( 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 start = range.startContainer,
- startBlock = domUtils.isBlockElm(start) ? start : domUtils.findParent(start,function(node){return domUtils.isBlockElm(node)}),
+ var orgFn = me.hasContents;
+ me.hasContents = function(){
+ if(me.queryCommandValue('background')){
+ return true
+ }
+ return orgFn.apply(me,arguments);
+ };
+ return {
+ bindEvents: {
+ 'getAllHtml': function (type, headHtml) {
+ var body = this.body,
+ su = domUtils.getComputedStyle(body, "background-image"),
+ url = "";
+ if (su.indexOf(me.options.imagePath) > 0) {
+ url = su.substring(su.indexOf(me.options.imagePath), su.length - 1).replace(/"|\(|\)/ig, "");
+ } else {
+ url = su != "none" ? su.replace(/url\("?|"?\)/ig, "") : "";
+ }
+ var html = ' ';
+ headHtml.push(html);
+ },
+ 'aftersetcontent': function () {
+ if(isSetColored == false) setBackground();
+ }
+ },
+ inputRule: function (root) {
+ isSetColored = false;
+ utils.each(root.getNodesByTagName('p'), function (p) {
+ var styles = p.getAttr('data-background');
+ if (styles) {
+ isSetColored = true;
+ setBackground(stringToObj(styles));
+ p.parentNode.removeChild(p);
+ }
+ })
+ },
+ outputRule: function (root) {
+ var me = this,
+ styles = (utils.cssRule(cssRuleId, me.document) || '').replace(/[\n\r]+/g, '').match(reg);
+ if (styles) {
+ root.appendChild(UE.uNode.createElement('
'));
+ }
+ },
+ commands: {
+ 'background': {
+ execCommand: function (cmd, obj) {
+ setBackground(obj);
+ },
+ queryCommandValue: function () {
+ var me = this,
+ styles = (utils.cssRule(cssRuleId, me.document) || '').replace(/[\n\r]+/g, '').match(reg);
+ return styles ? stringToObj(styles[1]) : null;
+ },
+ notNeedUndo: true
+ }
+ }
+ }
+});
- end = range.endContainer,
- endBlock = domUtils.isBlockElm(end) ? end : domUtils.findParent(end,function(node){return domUtils.isBlockElm(node)});
+// plugins/image.js
+/**
+ * 图片插入、排版插件
+ * @file
+ * @since 1.2.6.1
+ */
- //处理一下li
- startBlock = domUtils.findParentByTagName(startBlock,'li',true) || startBlock;
- endBlock = domUtils.findParentByTagName(endBlock,'li',true) || endBlock;
+/**
+ * 图片对齐方式
+ * @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', '');
+ }
- 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);
}
+ range.selectNode(img).select();
}
- }
-
- 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);
+ domUtils.setStyle(img, 'float', align == 'none' ? '' : align);
+ if(align == 'none'){
+ domUtils.removeAttributes(img,'align');
}
- }
-
-
-
-
- } 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 );
+ break;
+ case 'center':
+ if (me.queryCommandValue('imagefloat') != 'center') {
+ pN = img.parentNode;
+ domUtils.setStyle(img, 'float', '');
+ domUtils.removeAttributes(img,'align');
+ tmpNode = img;
+ while (pN && domUtils.getChildCount(pN, function (node) {
+ return !domUtils.isBr(node) && !domUtils.isWhitespace(node);
+ }) == 1
+ && (dtd.$inline[pN.tagName] || pN.tagName == 'A')) {
+ tmpNode = pN;
+ pN = pN.parentNode;
+ }
+ range.setStartBefore(tmpNode).setCursor(false);
+ pN = me.document.createElement('div');
+ pN.appendChild(tmpNode);
+ domUtils.setStyle(tmpNode, 'float', '');
+
+ me.execCommand('insertHtml', '' + pN.innerHTML + ' ');
+
+ tmpNode = me.document.getElementById('_img_parent_tmp');
+ tmpNode.removeAttribute('id');
+ tmpNode = tmpNode.firstChild;
+ range.selectNode(tmpNode).select();
+ //去掉后边多余的元素
+ next = tmpNode.parentNode.nextSibling;
+ if (next && domUtils.isEmptyNode(next)) {
+ domUtils.remove(next);
}
- }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;
+ break;
}
- //调整结束
- 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;
- }
+ }
+ }
+ },
+ 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');
- preNode = node;
- node = node.parentNode;
- }
+ 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;
- 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);
- }
- }
+ if (range.collapsed) return -1;
- }
- range.moveToBookmark( bookmark ).select();
- },
- queryCommandState : function() {
- return getObj(this) ? 1 : 0;
+ startNode = range.getClosedNode();
+ if (startNode && startNode.nodeType == 1 && startNode.tagName == 'IMG') {
+ return 0;
}
- };
+ return -1;
+ }
};
-
-
-// plugins/convertcase.js
-/**
- * 大小写转换
- * @file
- * @since 1.2.6.1
- */
/**
- * 把选区内文本变大写,与“tolowercase”命令互斥
- * @command touppercase
+ * 插入图片
+ * @command insertimage
* @method execCommand
* @param { String } cmd 命令字符串
+ * @param { Object } opt 属性键值对,这些属性都将被复制到当前插入图片
+ * @remind 该命令第二个参数可接受一个图片配置项对象的数组,可以插入多张图片,
+ * 此时数组的每一个元素都是一个Object类型的图片属性集合。
* @example
* ```javascript
- * editor.execCommand( 'touppercase' );
+ * editor.execCommand( 'insertimage', {
+ * src:'a/b/c.jpg',
+ * width:'100',
+ * height:'100'
+ * } );
* ```
- */
-
-/**
- * 把选区内文本变小写,与“touppercase”命令互斥
- * @command tolowercase
- * @method execCommand
- * @param { String } cmd 命令字符串
* @example
* ```javascript
- * editor.execCommand( 'tolowercase' );
+ * editor.execCommand( 'insertimage', [{
+ * src:'a/b/c.jpg',
+ * width:'100',
+ * height:'100'
+ * },{
+ * src:'a/b/d.jpg',
+ * width:'100',
+ * height:'100'
+ * }] );
* ```
*/
-UE.commands['touppercase'] =
-UE.commands['tolowercase'] = {
- execCommand:function (cmd) {
- var me = this;
- var rng = me.selection.getRange();
- if(rng.collapsed){
- return rng;
+
+UE.commands['insertimage'] = {
+ execCommand:function (cmd, opt) {
+
+ opt = utils.isArray(opt) ? opt : [opt];
+ if (!opt.length) {
+ return;
}
- 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) ) {
+ var me = this,
+ range = me.selection.getRange(),
+ img = range.getClosedNode();
- if ( curNode.nodeType == 3 ) {
- curNode.nodeValue = curNode.nodeValue[cmd == 'touppercase' ? 'toUpperCase' : 'toLowerCase']();
+ if(me.fireEvent('beforeinsertimage', opt) === true){
+ return;
+ }
+
+ function unhtmlData(imgCi) {
+
+ utils.each('width,height,border,hspace,vspace'.split(','), function (item) {
+
+ if (imgCi[item]) {
+ imgCi[item] = parseInt(imgCi[item], 10) || 0;
+ }
+ });
+
+ utils.each('src,_src'.split(','), function (item) {
+
+ if (imgCi[item]) {
+ imgCi[item] = utils.unhtmlForUrl(imgCi[item]);
+ }
+ });
+ utils.each('title,alt'.split(','), function (item) {
+
+ if (imgCi[item]) {
+ imgCi[item] = utils.unhtml(imgCi[item]);
+ }
+ });
+ }
+
+ if (img && /img/i.test(img.tagName) && (img.className != "edui-faked-video" || img.className.indexOf("edui-upload-video")!=-1) && !img.getAttribute("word_img")) {
+ var first = opt.shift();
+ var floatStyle = first['floatStyle'];
+ delete first['floatStyle'];
+//// img.style.border = (first.border||0) +"px solid #000";
+//// img.style.margin = (first.margin||0) +"px";
+// img.style.cssText += ';margin:' + (first.margin||0) +"px;" + 'border:' + (first.border||0) +"px solid #000";
+ domUtils.setAttributes(img, first);
+ me.execCommand('imagefloat', floatStyle);
+ if (opt.length > 0) {
+ range.setStartAfter(img).setCursor(false, true);
+ me.execCommand('insertimage', opt);
}
- curNode = domUtils.getNextDomNode( curNode, true, filterFn );
- if(curNode === bkEnd){
- break;
+
+ } else {
+ var html = [], str = '', ci;
+ ci = opt[0];
+ if (opt.length == 1) {
+ unhtmlData(ci);
+
+ str = ' ';
+ if (ci['floatStyle'] == 'center') {
+ str = '' + str + ' ';
+ }
+ html.push(str);
+
+ } else {
+ for (var i = 0; ci = opt[i++];) {
+ unhtmlData(ci);
+ str = ' ';
+ html.push(str);
+ }
}
+ me.execCommand('insertHtml', html.join(''));
}
- rng.moveToBookmark(bk).select();
+
+ me.fireEvent('afterinsertimage', opt)
}
};
-
-
-// plugins/indent.js
+
+// plugins/justify.js
/**
- * 首行缩进
+ * 段落格式
* @file
* @since 1.2.6.1
*/
/**
- * 缩进
- * @command indent
+ * 段落对齐方式
+ * @command justify
* @method execCommand
* @param { String } cmd 命令字符串
+ * @param { String } align 对齐方式:left => 居左,right => 居右,center => 居中,justify => 两端对齐
* @example
* ```javascript
- * editor.execCommand( 'indent' );
+ * editor.execCommand( 'justify', 'center' );
* ```
*/
-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;
- }
+/**
+ * 如果选区所在位置是段落区域,返回当前段落对齐方式
+ * @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/print.js
+
+
+// plugins/font.js
/**
- * 打印
+ * 字体颜色,背景色,字号,字体,下划线,删除线
* @file
* @since 1.2.6.1
*/
/**
- * 打印
- * @command print
+ * 字体颜色
+ * @command forecolor
* @method execCommand
* @param { String } cmd 命令字符串
+ * @param { String } value 色值(必须十六进制)
* @example
* ```javascript
- * editor.execCommand( 'print' );
+ * editor.execCommand( 'forecolor', '#000' );
* ```
*/
-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 forecolor
+ * @method queryCommandValue
+ * @param { String } cmd 命令字符串
+ * @return { String } 返回字体颜色
+ * @example
+ * ```javascript
+ * editor.queryCommandValue( 'forecolor' );
+ * ```
*/
/**
- * 选中所有内容
- * @command selectall
+ * 字体背景颜色
+ * @command backcolor
* @method execCommand
* @param { String } cmd 命令字符串
+ * @param { String } value 色值(必须十六进制)
* @example
* ```javascript
- * editor.execCommand( 'selectall' );
+ * editor.execCommand( 'backcolor', '#000' );
* ```
*/
-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 backcolor
+ * @method queryCommandValue
+ * @param { String } cmd 命令字符串
+ * @return { String } 返回字体背景颜色
+ * @example
+ * ```javascript
+ * editor.queryCommandValue( 'backcolor' );
+ * ```
*/
/**
- * 段落格式
- * @command paragraph
+ * 字体大小
+ * @command fontsize
* @method execCommand
* @param { String } cmd 命令字符串
- * @param {String} style 标签值为:'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'
- * @param {Object} attrs 标签的属性
+ * @param { String } value 字体大小
* @example
* ```javascript
- * editor.execCommand( 'Paragraph','h1','{
- * class:'test'
- * }' );
+ * editor.execCommand( 'fontsize', '14px' );
* ```
*/
-
/**
- * 返回选区内节点标签名
- * @command paragraph
+ * 返回选区字体大小
+ * @command fontsize
* @method queryCommandValue
* @param { String } cmd 命令字符串
- * @return { String } 节点标签名
+ * @return { String } 返回字体大小
* @example
* ```javascript
- * editor.queryCommandValue( 'Paragraph' );
+ * editor.queryCommandValue( 'fontsize' );
* ```
*/
-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;
+/**
+ * 字体样式
+ * @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' );
+ * ```
+ */
- 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);
-
- }
+/**
+ * 字体下划线,与删除线互斥
+ * @command underline
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'underline' );
+ * ```
+ */
- tmpRange.insertNode( para );
+/**
+ * 字体删除线,与下划线互斥
+ * @command strikethrough
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'strikethrough' );
+ * ```
+ */
- 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);
- }
+/**
+ * 字体边框
+ * @command fontborder
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'fontborder' );
+ * ```
+ */
- //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 );
- }
+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'
- }
- if( utils.indexOf(notExchange,parent.tagName)!=-1){
- current = parent;
- }else{
- current = para;
- }
+ };
+ 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;
+ }
+ }
- current = domUtils.getNextDomNode( current, false, filterFn );
- } else {
- current = domUtils.getNextDomNode( current, true, filterFn );
+ }
+ function mergeChild(rng,cmdName,value){
+ if(needSetChild[cmdName]){
+ rng.adjustmentBoundary();
+ if(!rng.collapsed && rng.startContainer.nodeType == 1){
+ var start = rng.startContainer.childNodes[rng.startOffset];
+ if(start && domUtils.isTagNode(start,'span')){
+ var bk = rng.createBookmark();
+ utils.each(domUtils.getElementsByTagName(start, 'span'), function (span) {
+ if (!span.parentNode || domUtils.isBookmarkNode(span))return;
+ if(cmdName == 'backcolor' && domUtils.getComputedStyle(span,'background-color').toLowerCase() === value){
+ return;
+ }
+ domUtils.removeStyle(span,needSetChild[cmdName]);
+ if(span.style.cssText.replace(/^\s+$/,'').length == 0){
+ domUtils.remove(span,true)
+ }
+ });
+ rng.moveToBookmark(bk)
}
}
- 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);
+ }
+
+ }
+ 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;
}
- node = txt.nextSibling;
- if(node && domUtils.isWhitespace(node)){
- domUtils.remove(node);
+ if (next.style.cssText == span.style.cssText) {
+ domUtils.moveChild(next, span);
+ domUtils.remove(next);
}
+ if (span.nextSibling === next)
+ break;
+ next = span.nextSibling;
}
-
}
- 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);
+ 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;
}
}
- //trace:1097 原来有true,原因忘了,但去了就不能清除多余的占位符了
- range.select();
+ });
+ rng.moveToBookmark(bk);
+ mergeChild(rng,cmdName,value)
+ }
- 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;
+ 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')
// }
// }
// }
- return domUtils.filterNodeList(editor.selection.getStartElementPath(),function(n){return n && n.nodeType == 1 && n.getAttribute('dir')});
+// });
+ });
+// 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;
- },
- doDirectionality = function(range,editor,forward){
-
- var bookmark,
- filterFn = function( node ) {
- return node.nodeType == 1 ? !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace(node);
- },
+ if (value == 'default') {
- obj = getObj( editor );
+ if (range.collapsed) {
+ text = me.document.createTextNode('font');
+ range.insertNode(text).select();
- 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;
+ }
+ me.execCommand('removeFormat', 'span,a', style);
+ if (text) {
+ range.setStartBefore(text).collapse(true);
+ domUtils.remove(text);
+ }
+ mergesibling(range,cmdName,value);
+ range.select()
} else {
- //没有遍历到,添加一个block节点
- var p = range.document.createElement( 'p' );
- p.setAttribute( 'dir', forward );
- var frag = tmpRange.extractContents();
- p.appendChild( frag );
- tmpRange.insertNode( p );
- current = p;
- }
+ if (!range.collapsed) {
+ if (needCmd[cmd] && me.queryCommandValue(cmd)) {
+ me.execCommand('removeFormat', 'span,a', style);
+ }
+ range = me.selection.getRange();
- current = domUtils.getNextDomNode( current, false, filterFn );
- } else {
- current = domUtils.getNextDomNode( current, true, filterFn );
- }
- }
- return range.moveToBookmark( bookmark2 ).moveToBookmark( bookmark );
- };
+ range.applyInlineStyle('span', {'style': style + ':' + value});
+ mergesibling(range, cmdName,value);
+ range.select();
+ } else {
- /**
- * 文字输入方向
- * @command directionality
- * @method execCommand
- * @param { String } cmdName 命令字符串
- * @param { String } forward 传入'ltr'表示从左向右输入,传入'rtl'表示从右向左输入
- * @example
- * ```javascript
- * editor.execCommand( 'directionality', 'ltr');
- * ```
- */
+ 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);
- /**
- * 查询当前选区的文字输入方向
- * @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);
- }
+ span = domUtils.findParentByTagName(text, 'span', true);
+ range.setStartBefore(text);
- range.select();
- return true;
- },
- queryCommandValue : function() {
- var node = getObj(this);
- return node ? node.getAttribute('dir') : 'ltr';
- }
- };
-})();
+ }
+ span && (span.style.cssText += ';' + style + ':' + value);
+ range.collapse(true).select();
-
-
-// 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] ){
+ } else {
+ range.insertNode(text);
+ range.selectNode(text).select();
+ span = range.document.createElement('span');
- 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();
+ if (needCmd[cmd]) {
+ //a标签内的不处理跳过
+ if (domUtils.findParentByTagName(text, 'a', true)) {
+ range.setStartBefore(text).setCursor();
+ domUtils.remove(text);
+ return;
+ }
+ me.execCommand('removeFormat', 'span,a', style);
+ }
- }else{
- tmp = me.document.createElement('br');
- range.insertNode(tmp);
- range.setStartBefore(tmp).setCursor();
+ 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();
- }
- return true;
- }
+ //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;
+ }
+ }
- },
- //边界在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;
+ 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/time.js
+// plugins/link.js
/**
- * 插入时间和日期
+ * 超链接
* @file
* @since 1.2.6.1
*/
/**
- * 插入时间,默认格式:12:59:59
- * @command time
+ * 插入超链接
+ * @command link
* @method execCommand
* @param { String } cmd 命令字符串
+ * @param { Object } options 设置自定义属性,例如:url、title、target
* @example
* ```javascript
- * editor.execCommand( 'time');
+ * editor.execCommand( 'link', '{
+ * url:'ueditor.baidu.com',
+ * title:'ueditor',
+ * target:'_blank'
+ * }' );
+ * ```
+ */
+/**
+ * 返回当前选中的第一个超链接节点
+ * @command link
+ * @method queryCommandValue
+ * @param { String } cmd 命令字符串
+ * @return { Element } 超链接节点
+ * @example
+ * ```javascript
+ * editor.queryCommandValue( 'link' );
* ```
*/
/**
- * 插入日期,默认格式:2013-08-30
- * @command date
+ * 取消超链接
+ * @command unlink
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
- * editor.execCommand( 'date');
+ * editor.execCommand( 'unlink');
* ```
*/
-UE.commands['time'] = UE.commands["date"] = {
- execCommand : function(cmd, format){
- var date = new Date;
- function formatTime(date, format) {
- var hh = ('0' + date.getHours()).slice(-2),
- ii = ('0' + date.getMinutes()).slice(-2),
- ss = ('0' + date.getSeconds()).slice(-2);
- format = format || 'hh:ii:ss';
- return format.replace(/hh/ig, hh).replace(/ii/ig, ii).replace(/ss/ig, ss);
+UE.plugins['link'] = function(){
+ function optimize( range ) {
+ var start = range.startContainer,end = range.endContainer;
+
+ if ( start = domUtils.findParentByTagName( start, 'a', true ) ) {
+ range.setStartBefore( start );
}
- function formatDate(date, format) {
- var yyyy = ('000' + date.getFullYear()).slice(-4),
- yy = yyyy.slice(-2),
- mm = ('0' + (date.getMonth()+1)).slice(-2),
- dd = ('0' + date.getDate()).slice(-2);
- format = format || 'yyyy-mm-dd';
- return format.replace(/yyyy/ig, yyyy).replace(/yy/ig, yy).replace(/mm/ig, mm).replace(/dd/ig, dd);
+ if ( end = domUtils.findParentByTagName( end, 'a', true ) ) {
+ range.setEndAfter( end );
}
-
- 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;
+ UE.commands['unlink'] = {
+ execCommand : function() {
+ var range = this.selection.getRange(),
+ bookmark;
+ if(range.collapsed && !domUtils.findParentByTagName( range.startContainer, 'a', true )){
+ return;
}
- return 0;
-
+ 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();
+ }
-
-
-// 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']});
+ if ( rngClone.collapsed ) {
+ var a = range.document.createElement( 'a'),
+ text = '';
+ if(opt.textValue){
- /**
- * 行距
- * @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' );
- * ```
- */
+ 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);
- me.commands['lineheight'] = {
- execCommand : function( cmdName,value ) {
- this.execCommand('paragraph','p',{style:'line-height:'+ (value == "1" ? "normal" : value + 'em') });
- return true;
},
queryCommandValue : function() {
- var pN = domUtils.filterNodeList(this.selection.getStartElementPath(),function(node){return domUtils.isBlockElm(node)});
- if(pN){
- var value = domUtils.getComputedStyle(pN,'line-height');
- return value == 'normal' ? 1 : value.replace(/[^\d.]*/ig,"");
+ 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/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
+// plugins/removeformat.js
/**
- * 清空文档插件
+ * 清除格式
* @file
* @since 1.2.6.1
*/
/**
- * 清空文档
- * @command cleardoc
+ * 清除文字样式
+ * @command removeformat
* @method execCommand
* @param { String } cmd 命令字符串
+ * @param {String} tags 以逗号隔开的标签。如:strong
+ * @param {String} style 样式如:color
+ * @param {String} attrs 属性如:width
* @example
* ```javascript
- * //editor 是编辑器实例
- * editor.execCommand('cleardoc');
+ * editor.execCommand( 'removeformat', 'strong','color','width' );
* ```
*/
-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);
+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;
+ };
-
-
-// plugins/anchor.js
-/**
- * 锚点插件,为UEditor提供插入锚点支持
- * @file
- * @since 1.2.6.1
- */
-UE.plugin.register('anchor', function (){
-
- return {
- bindEvents:{
- 'ready':function(){
- utils.cssRule('anchor',
- '.anchorclass{background: url(\''
- + this.options.themePath
- + this.options.theme +'/images/anchor.gif\') no-repeat scroll left center transparent;cursor: auto;display: inline-block;height: 16px;width: 15px;}',
- this.document);
+ 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');
- 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);
- }
- })
+ bookmark = range.createBookmark();
- });
+ node = bookmark.start;
- /**
- * 插入分页符
- * @command pagebreak
- * @method execCommand
- * @param { String } cmd 命令字符串
- * @remind 在表格中插入分页符会把表格切分成两部分
- * @remind 获取编辑器内的数据时, 编辑器会把分页符转换成“_ueditor_page_break_tag_”字符串,
- * 以便于提交数据到服务器端后处理分页。
- * @example
- * ```javascript
- * editor.execCommand( 'pagebreak'); //插入一个hr标签,带有样式类名pagebreak
- * ```
- */
+ //切开始
+ while ( (parent = node.parentNode) && !domUtils.isBlockElm( parent ) ) {
+ domUtils.breakParent( node, parent );
- 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),
+ domUtils.clearEmptySibling( node );
+ }
+ if ( bookmark.end ) {
+ //切结束
+ node = bookmark.end;
+ while ( (parent = node.parentNode) && !domUtils.isBlockElm( parent ) ) {
+ domUtils.breakParent( node, parent );
+ domUtils.clearEmptySibling( node );
+ }
- 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);
+ //开始去除样式
+ var current = domUtils.getNextDomNode( bookmark.start, false, filter ),
+ next;
+ while ( current ) {
+ if ( current == bookmark.end ) {
+ break;
+ }
- } else {
- pN.parentNode.insertBefore(hr, pN);
- parents = domUtils.findParents(hr);
+ next = domUtils.getNextDomNode( current, true, filter );
- }
- pN = parents[1];
- if (hr !== pN) {
- domUtils.breakParent(hr, pN);
+ 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 );
+ }
+ }
+ }
}
- //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;
+ current = next;
}
-
}
- 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;
+ //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 );
}
- nextNode = hr.nextSibling;
- var pre = hr.previousSibling;
- if(isHr(pre)){
- domUtils.remove(pre);
- }else{
- pre && fillNode(pre);
+ pN = bookmark.end.parentNode;
+ if(bookmark.end && domUtils.isBlockElm(pN) && !dtd.$tableContent[pN.tagName]&& !dtd.$list[pN.tagName]){
+ domUtils.removeAttributes( pN,removeFormatAttributes );
}
-
- 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.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--;
}
- range.setEndAfter(hr).collapse(false);
+ domUtils.remove(node);
+ node = tmp;
}
- range.select(true);
-
- }
-
- }
- };
-};
-
-// plugins/wordimage.js
-///import core
-///commands 本地图片引导上传
-///commandsName WordImage
-///commandsTitle 本地图片引导上传
-///commandsDialog dialogs\wordimage
+ 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);
-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;
- }
+ node = tmp;
}
- return -1;
- },
- notNeedUndo:true
- }
- },
- inputRule : function (root) {
- utils.each(root.getNodesByTagName('img'), function (img) {
- var attrs = img.attrs,
- flag = parseInt(attrs.width) < 128 || parseInt(attrs.height) < 43,
- opt = me.options,
- src = opt.UEDITOR_HOME_URL + 'themes/default/images/spacer.gif';
- if (attrs['src'] && /^(?:(file:\/+))/.test(attrs['src'])) {
- img.setAttr({
- width:attrs.width,
- height:attrs.height,
- alt:attrs.alt,
- word_img: attrs.src,
- src:src,
- 'style':'background:url(' + ( flag ? opt.themePath + opt.theme + '/images/word.gif' : opt.langPath + opt.lang + '/images/localimage.png') + ') no-repeat center center;border:1px solid #ddd'
- })
- }
- })
- }
- }
-});
-
-// plugins/dragdrop.js
-UE.plugins['dragdrop'] = function (){
-
- var me = this;
- me.ready(function(){
- domUtils.on(this.body,'dragend',function(){
- var rng = me.selection.getRange();
- var node = rng.getClosedNode()||me.selection.getStart();
- if(node && node.tagName == 'IMG'){
- var pre = node.previousSibling,next;
- while(next = node.nextSibling){
- if(next.nodeType == 1 && next.tagName == 'SPAN' && !next.firstChild){
- domUtils.remove(next)
- }else{
- break;
- }
}
+ }
- if((pre && pre.nodeType == 1 && !domUtils.isEmptyBlock(pre) || !pre) && (!next || next && !domUtils.isEmptyBlock(next))){
- if(pre && pre.tagName == 'P' && !domUtils.isEmptyBlock(pre)){
- pre.appendChild(node);
- domUtils.moveChild(next,pre);
- domUtils.remove(next);
- }else if(next && next.tagName == 'P' && !domUtils.isEmptyBlock(next)){
- next.insertBefore(node,next.firstChild);
- }
- if(pre && pre.tagName == 'P' && domUtils.isEmptyBlock(pre)){
- domUtils.remove(pre)
- }
- if(next && next.tagName == 'P' && domUtils.isEmptyBlock(next)){
- domUtils.remove(next)
- }
- rng.selectNode(node).select();
- me.fireEvent('saveScene');
+ range = this.selection.getRange();
+ doRemove( range );
+ range.select();
- }
+ }
- }
+ };
- })
- });
- 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
+
+
+// plugins/blockquote.js
/**
- * undo redo
+ * 添加引用
* @file
* @since 1.2.6.1
*/
/**
- * 撤销上一次执行的命令
- * @command undo
+ * 添加引用
+ * @command blockquote
* @method execCommand
* @param { String } cmd 命令字符串
* @example
* ```javascript
- * editor.execCommand( 'undo' );
+ * editor.execCommand( 'blockquote' );
* ```
*/
/**
- * 重做上一次执行的命令
- * @command redo
+ * 添加引用
+ * @command blockquote
* @method execCommand
* @param { String } cmd 命令字符串
+ * @param { Object } attrs 节点属性
* @example
* ```javascript
- * editor.execCommand( 'redo' );
+ * editor.execCommand( 'blockquote',{
+ * style: "color: red;"
+ * } );
* ```
*/
-UE.plugins['undo'] = function () {
- var saveSceneTimer;
- var me = this,
- maxUndoCount = me.options.maxUndoCount || 20,
- maxInputCount = me.options.maxInputCount || 20,
- fillchar = new RegExp(domUtils.fillChar + '|<\/hr>', 'gi');// ie会产生多余的
- var noNeedFillCharTags = {
- ol:1,ul:1,table:1,tbody:1,tr:1,body:1
- };
- var orgState = me.options.autoClearEmptyNode;
- function compareAddr(indexA, indexB) {
- if (indexA.length != indexB.length)
- return 0;
- for (var i = 0, l = indexA.length; i < l; i++) {
- if (indexA[i] != indexB[i])
- return 0
- }
- return 1;
- }
- function compareRangeAddress(rngAddrA, rngAddrB) {
- if (rngAddrA.collapsed != rngAddrB.collapsed) {
- return 0;
- }
- if (!compareAddr(rngAddrA.startAddress, rngAddrB.startAddress) || !compareAddr(rngAddrA.endAddress, rngAddrB.endAddress)) {
- return 0;
- }
- return 1;
+UE.plugins['blockquote'] = function(){
+ var me = this;
+ function getObj(editor){
+ return domUtils.filterNodeList(editor.selection.getStartElementPath(),'blockquote');
}
-
- 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);
+ 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);
}
- }
- 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);
+
+ 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);
+ }
+
+ }
}
- }
- 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);
+ 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);
+ }
}
- })
- }
- 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];
+ } else {
- 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();
+ var tmpRange = range.cloneRange(),
+ node = tmpRange.startContainer.nodeType == 1 ? tmpRange.startContainer : tmpRange.startContainer.parentNode,
+ preNode = node,
+ doEnd = 1;
- };
- 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;
- };
- }
+ //调整开始
+ 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);
+ }
- me.undoManger = new UndoManager();
- me.undoManger.editor = me;
- function saveScene() {
- this.undoManger.save();
- }
+ break;
+ }
+ if ( !blockquote[node.tagName] ) {
+ if ( range.collapsed ) {
+ tmpRange.selectNode( preNode );
+ } else{
+ tmpRange.setStartBefore( preNode);
+ }
+ break;
+ }
- me.addListener('saveScene', function () {
- var args = Array.prototype.splice.call(arguments,1);
- this.undoManger.save.apply(this.undoManger,args);
- });
+ preNode = node;
+ node = node.parentNode;
+ }
-// me.addListener('beforeexeccommand', saveScene);
-// me.addListener('afterexeccommand', saveScene);
+ //调整结束
+ if ( doEnd ) {
+ preNode = node = node = tmpRange.endContainer.nodeType == 1 ? tmpRange.endContainer : tmpRange.endContainer.parentNode;
+ while ( 1 ) {
- 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
- };
+ if ( domUtils.isBody( node ) ) {
+ if ( preNode !== node ) {
- 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
+ tmpRange.setEndAfter( preNode );
- },
- 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
+ } else {
+ tmpRange.setEnd( node, node.childNodes.length );
+ }
- });
- var isCollapsed = true;
- me.addListener('keydown', function (type, evt) {
+ break;
+ }
+ if ( !blockquote[node.tagName] ) {
+ tmpRange.setEndAfter( preNode );
+ break;
+ }
- var me = this;
- var keyCode = evt.keyCode || evt.which;
- if (!keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
- if (inputType)
- return;
+ preNode = node;
+ node = node.parentNode;
+ }
- 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;
+
+ 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;
}
- });
- //扩展实例,添加关闭和开启命令undo
- me.stopCmdUndo = function(){
- me.__hasEnterExecCommand = true;
};
- me.startCmdUndo = function(){
- me.__hasEnterExecCommand = false;
- }
};
-
-
-// plugins/copy.js
-UE.plugin.register('copy', function () {
-
- var me = this;
-
- function initZeroClipboard() {
-
- ZeroClipboard.config({
- debug: false,
- swfPath: me.options.UEDITOR_HOME_URL + 'third-party/zeroclipboard/ZeroClipboard.swf'
- });
-
- var client = me.zeroclipboard = new ZeroClipboard();
-
- // 复制内容
- client.on('copy', function (e) {
- var client = e.client,
- rng = me.selection.getRange(),
- div = document.createElement('div');
-
- div.appendChild(rng.cloneContents());
- client.setText(div.innerText || div.textContent);
- client.setHtml(div.innerHTML);
- rng.select();
- });
- // hover事件传递到target
- client.on('mouseover mouseout', function (e) {
- var target = e.target;
- if (e.type == 'mouseover') {
- domUtils.addClass(target, 'edui-state-hover');
- } else if (e.type == 'mouseout') {
- domUtils.removeClasses(target, 'edui-state-hover');
- }
- });
- // flash加载不成功
- client.on('wrongflash noflash', function () {
- ZeroClipboard.destroy();
- });
- }
-
- return {
- bindEvents: {
- 'ready': function () {
- if (!browser.ie) {
- if (window.ZeroClipboard) {
- initZeroClipboard();
- } else {
- utils.loadFile(document, {
- src: me.options.UEDITOR_HOME_URL + "third-party/zeroclipboard/ZeroClipboard.js",
- tag: "script",
- type: "text/javascript",
- defer: "defer"
- }, function () {
- initZeroClipboard();
- });
- }
- }
- }
- },
- commands: {
- 'copy': {
- execCommand: function (cmd) {
- if (!me.document.execCommand('copy')) {
- alert(me.getLang('copymsg'));
- }
- }
- }
- }
- }
-});
-
-
-// plugins/paste.js
-///import core
-///import plugins/inserthtml.js
-///import plugins/undo.js
-///import plugins/serialize.js
-///commands 粘贴
-///commandsName PastePlain
-///commandsTitle 纯文本粘贴模式
-/**
- * @description 粘贴
- * @author zhanyi
- */
-UE.plugins['paste'] = function () {
- function getClipboardData(callback) {
- var doc = this.document;
- if (doc.getElementById('baidu_pastebin')) {
- return;
- }
- var range = this.selection.getRange(),
- bk = range.createBookmark(),
- //创建剪贴的容器div
- pastebin = doc.createElement('div');
- pastebin.id = 'baidu_pastebin';
- // Safari 要求div必须有内容,才能粘贴内容进来
- browser.webkit && pastebin.appendChild(doc.createTextNode(domUtils.fillChar + domUtils.fillChar));
- doc.body.appendChild(pastebin);
- //trace:717 隐藏的span不能得到top
- //bk.start.innerHTML = ' ';
- bk.start.style.display = '';
- pastebin.style.cssText = "position:absolute;width:1px;height:1px;overflow:hidden;left:-1000px;white-space:nowrap;top:" +
- //要在现在光标平行的位置加入,否则会出现跳动的问题
- domUtils.getXY(bk.start).y + 'px';
-
- range.selectNodeContents(pastebin).select(true);
-
- setTimeout(function () {
- if (browser.webkit) {
- for (var i = 0, pastebins = doc.querySelectorAll('#baidu_pastebin'), pi; pi = pastebins[i++];) {
- if (domUtils.isEmptyNode(pi)) {
- domUtils.remove(pi);
- } else {
- pastebin = pi;
- break;
- }
- }
- }
- try {
- pastebin.parentNode.removeChild(pastebin);
- } catch (e) {
- }
- range.moveToBookmark(bk).select(true);
- callback(pastebin);
- }, 0);
- }
-
- var me = this;
-
- me.setOpt({
- retainOnlyLabelPasted : false
- });
-
- var txtContent, htmlContent, address;
-
- function getPureHtml(html){
- return html.replace(/<(\/?)([\w\-]+)([^>]*)>/gi, function (a, b, tagName, attrs) {
- tagName = tagName.toLowerCase();
- if ({img: 1}[tagName]) {
- return a;
- }
- attrs = attrs.replace(/([\w\-]*?)\s*=\s*(("([^"]*)")|('([^']*)')|([^\s>]+))/gi, function (str, atr, val) {
- if ({
- 'src': 1,
- 'href': 1,
- 'name': 1
- }[atr.toLowerCase()]) {
- return atr + '=' + val + ' '
- }
- return ''
- });
- if ({
- 'span': 1,
- 'div': 1
- }[tagName]) {
- return ''
- } else {
-
- return '<' + b + tagName + ' ' + utils.trim(attrs) + '>'
- }
-
- });
- }
- function filter(div) {
- var html;
- if (div.firstChild) {
- //去掉cut中添加的边界值
- var nodes = domUtils.getElementsByTagName(div, 'span');
- for (var i = 0, ni; ni = nodes[i++];) {
- if (ni.id == '_baidu_cut_start' || ni.id == '_baidu_cut_end') {
- domUtils.remove(ni);
- }
- }
-
- if (browser.webkit) {
-
- var brs = div.querySelectorAll('div br');
- for (var i = 0, bi; bi = brs[i++];) {
- var pN = bi.parentNode;
- if (pN.tagName == 'DIV' && pN.childNodes.length == 1) {
- pN.innerHTML = '
';
- domUtils.remove(pN);
- }
- }
- var divs = div.querySelectorAll('#baidu_pastebin');
- for (var i = 0, di; di = divs[i++];) {
- var tmpP = me.document.createElement('p');
- di.parentNode.insertBefore(tmpP, di);
- while (di.firstChild) {
- tmpP.appendChild(di.firstChild);
- }
- domUtils.remove(di);
- }
-
- var metas = div.querySelectorAll('meta');
- for (var i = 0, ci; ci = metas[i++];) {
- domUtils.remove(ci);
- }
-
- var brs = div.querySelectorAll('br');
- for (i = 0; ci = brs[i++];) {
- if (/^apple-/i.test(ci.className)) {
- domUtils.remove(ci);
- }
- }
- }
- if (browser.gecko) {
- var dirtyNodes = div.querySelectorAll('[_moz_dirty]');
- for (i = 0; ci = dirtyNodes[i++];) {
- ci.removeAttribute('_moz_dirty');
- }
- }
- if (!browser.ie) {
- var spans = div.querySelectorAll('span.Apple-style-span');
- for (var i = 0, ci; ci = spans[i++];) {
- domUtils.remove(ci, true);
- }
- }
-
- //ie下使用innerHTML会产生多余的\r\n字符,也会产生 这里过滤掉
- html = div.innerHTML;//.replace(/>(?:(\s| )*?)<');
-
- //过滤word粘贴过来的冗余属性
- html = UE.filterWord(html);
- //取消了忽略空白的第二个参数,粘贴过来的有些是有空白的,会被套上相关的标签
- var root = UE.htmlparser(html);
- //如果给了过滤规则就先进行过滤
- if (me.options.filterRules) {
- UE.filterNode(root, me.options.filterRules);
- }
- //执行默认的处理
- me.filterInputRule(root);
- //针对chrome的处理
- if (browser.webkit) {
- var br = root.lastChild();
- if (br && br.type == 'element' && br.tagName == 'br') {
- root.removeChild(br)
- }
- utils.each(me.body.querySelectorAll('div'), function (node) {
- if (domUtils.isEmptyBlock(node)) {
- domUtils.remove(node,true)
- }
- })
- }
- html = {'html': root.toHtml()};
- me.fireEvent('beforepaste', html, root);
- //抢了默认的粘贴,那后边的内容就不执行了,比如表格粘贴
- if(!html.html){
- return;
- }
- root = UE.htmlparser(html.html,true);
- //如果开启了纯文本模式
- if (me.queryCommandState('pasteplain') === 1) {
- me.execCommand('insertHtml', UE.filterNode(root, me.options.filterTxtRules).toHtml(), true);
- } else {
- //文本模式
- UE.filterNode(root, me.options.filterTxtRules);
- txtContent = root.toHtml();
- //完全模式
- htmlContent = html.html;
-
- address = me.selection.getRange().createAddress(true);
- me.execCommand('insertHtml', me.getOpt('retainOnlyLabelPasted') === true ? getPureHtml(htmlContent) : htmlContent, true);
- }
- me.fireEvent("afterpaste", html);
- }
- }
-
- me.addListener('pasteTransfer', function (cmd, plainType) {
-
- if (address && txtContent && htmlContent && txtContent != htmlContent) {
- var range = me.selection.getRange();
- range.moveToAddress(address, true);
-
- if (!range.collapsed) {
-
- while (!domUtils.isBody(range.startContainer)
- ) {
- var start = range.startContainer;
- if(start.nodeType == 1){
- start = start.childNodes[range.startOffset];
- if(!start){
- range.setStartBefore(range.startContainer);
- continue;
- }
- var pre = start.previousSibling;
-
- if(pre && pre.nodeType == 3 && new RegExp('^[\n\r\t '+domUtils.fillChar+']*$').test(pre.nodeValue)){
- range.setStartBefore(pre)
- }
- }
- if(range.startOffset == 0){
- range.setStartBefore(range.startContainer);
- }else{
- break;
- }
-
- }
- while (!domUtils.isBody(range.endContainer)
- ) {
- var end = range.endContainer;
- if(end.nodeType == 1){
- end = end.childNodes[range.endOffset];
- if(!end){
- range.setEndAfter(range.endContainer);
- continue;
- }
- var next = end.nextSibling;
- if(next && next.nodeType == 3 && new RegExp('^[\n\r\t'+domUtils.fillChar+']*$').test(next.nodeValue)){
- range.setEndAfter(next)
- }
- }
- if(range.endOffset == range.endContainer[range.endContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length){
- range.setEndAfter(range.endContainer);
- }else{
- break;
- }
-
- }
-
- }
-
- range.deleteContents();
- range.select(true);
- me.__hasEnterExecCommand = true;
- var html = htmlContent;
- if (plainType === 2 ) {
- html = getPureHtml(html);
- } else if (plainType) {
- html = txtContent;
- }
- me.execCommand('inserthtml', html, true);
- me.__hasEnterExecCommand = false;
- var rng = me.selection.getRange();
- while (!domUtils.isBody(rng.startContainer) && !rng.startOffset &&
- rng.startContainer[rng.startContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length
- ) {
- rng.setStartBefore(rng.startContainer);
- }
- var tmpAddress = rng.createAddress(true);
- address.endAddress = tmpAddress.startAddress;
- }
- });
-
- me.addListener('ready', function () {
- domUtils.on(me.body, 'cut', function () {
- var range = me.selection.getRange();
- if (!range.collapsed && me.undoManger) {
- me.undoManger.save();
- }
- });
-
- //ie下beforepaste在点击右键时也会触发,所以用监控键盘才处理
- domUtils.on(me.body, browser.ie || browser.opera ? 'keydown' : 'paste', function (e) {
- if ((browser.ie || browser.opera) && ((!e.ctrlKey && !e.metaKey) || e.keyCode != '86')) {
- return;
- }
- getClipboardData.call(me, function (div) {
- filter(div);
- });
- });
-
- });
-
- me.commands['paste'] = {
- execCommand: function (cmd) {
- if (browser.ie) {
- getClipboardData.call(me, function (div) {
- filter(div);
- });
- me.document.execCommand('paste');
- } else {
- alert(me.getLang('pastemsg'));
- }
- }
- }
-};
-
-
-
-// plugins/puretxtpaste.js
+
+
+
+// plugins/convertcase.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)
+/**
+ * 把选区内文本变大写,与“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']();
}
- 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())
- }
+ curNode = domUtils.getNextDomNode( curNode, true, filterFn );
+ if(curNode === bkEnd){
+ break;
}
- }()
- });
- //暂时这里支持一下老版本的属性
- var pasteplain = me.options.pasteplain;
- /**
- * 启用或取消纯文本粘贴模式
- * @command pasteplain
- * @method execCommand
- * @param { String } cmd 命令字符串
- * @example
- * ```javascript
- * editor.queryCommandState( 'pasteplain' );
- * ```
- */
+ }
+ rng.moveToBookmark(bk).select();
+ }
+};
- /**
- * 查询当前是否处于纯文本粘贴模式
- * @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
+
+
+// plugins/indent.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'
- };
+/**
+ * 缩进
+ * @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;
+ }
- 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{box-sizing:border-box;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);
- }
- }
- }
- }
+// 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
+};
- 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)
+// plugins/preview.js
+/**
+ * 预览
+ * @file
+ * @since 1.2.6.1
+ */
- }else{
- n.setStyle('list-style-type',currentStyle)
- }
- })
+/**
+ * 预览
+ * @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
+};
- }
- 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);
- }
+// plugins/selectall.js
+/**
+ * 全选
+ * @file
+ * @since 1.2.6.1
+ */
- index = newChildrens.length;
+/**
+ * 选中所有内容
+ * @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);
}
- });
- if(newChildrens.length){
- li.children = newChildrens;
+ range.collapse(true);
}
- });
+ range.select(true);
+ },
+ notNeedUndo : 1
+ };
+
+
+ //快捷键
+ me.addshortcutkey({
+ "selectAll" : "ctrl+65"
});
- //进入编辑器的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]+\)/
+
+// 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 );
},
- 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
+ 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;
}
}
- return 'disc'
- }
- for(var p in orderlisttype){
- if(orderlisttype[p].test(content)){
- return p;
+ para.appendChild( tmpRange.extractContents() );
+ //需要内容占位
+ if(domUtils.isEmptyNode(para)){
+ domUtils.fillChar(range.document,para);
+
}
- }
- }
- utils.each(root.getNodesByTagName('p'),function(node){
- if(node.getAttr('class') != 'MsoListParagraph'){
- return
- }
+ tmpRange.insertNode( para );
- //word粘贴过来的会带有margin要去掉,但这样也可能会误命中一些央视
- node.setStyle('margin','');
- node.setStyle('margin-left','');
- node.setAttr('class','');
+ 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);
+ }
- 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);
+ //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{
- p.innerHTML(p.innerHTML().replace(orderlisttype[type],''));
+ domUtils.remove( para.parentNode, true );
}
+
+ }
+ if( utils.indexOf(notExchange,parent.tagName)!=-1){
+ current = parent;
}else{
- p.removeChild(p.firstChild())
+ current = para;
}
- 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;
+ 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);
}
- if(!list.parentNode && node && node.parentNode){
- node.parentNode.insertBefore(list,node)
+ node = txt.nextSibling;
+ if(node && domUtils.isWhitespace(node)){
+ domUtils.remove(node);
}
}
- var span = cacheNode.firstChild();
- if(span && span.type == 'element' && span.tagName == 'span' && /^\s*( )+\s*$/.test(span.innerText())){
- span.parentNode.removeChild(span)
- }
- })
- }
- });
+ }
+ range = doParagraph(range,style,attrs,sourceCmdName);
+ if(txt){
+ range.setStartBefore(txt).collapse(true);
+ pN = txt.parentNode;
- //调整索引标签
- me.addListener('contentchange',function(){
- adjustListStyle(me.document)
- });
+ domUtils.remove(txt);
- function adjustListStyle(doc,ignore){
- utils.each(domUtils.getElementsByTagName(doc,'ol ul'),function(node){
+ if(domUtils.isBlockElm(pN)&&domUtils.isEmptyNode(pN)){
+ domUtils.fillNode(this.document,pN);
+ }
- 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])
+ 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);
}
-
}
- 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)
- }
- }
+ //trace:1097 原来有true,原因忘了,但去了就不能清除多余的占位符了
+ range.select();
- 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;
+ return true;
+ },
+ queryCommandValue : function() {
+ var node = domUtils.filterNodeList(this.selection.getStartElementPath(),'p h1 h2 h3 h4 h5 h6');
+ return node ? node.tagName.toLowerCase() : '';
}
- 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();
+// 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);
+ },
- }
- preventAndSave();
- return;
+ 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 {
- 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;
+ //没有遍历到,添加一个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 );
+ };
- 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 {
+ /**
+ * 文字输入方向
+ * @command directionality
+ * @method execCommand
+ * @param { String } cmdName 命令字符串
+ * @param { String } forward 传入'ltr'表示从左向右输入,传入'rtl'表示从右向左输入
+ * @example
+ * ```javascript
+ * editor.execCommand( 'directionality', 'ltr');
+ * ```
+ */
- parentList.parentNode.insertBefore(li, parentList.nextSibling);
- if (domUtils.isEmptyNode(parentList)) {
- domUtils.remove(parentList);
- }
- }
- //嵌套不处理
- if (!dtd.$list[li.parentNode.tagName]) {
+ /**
+ * 查询当前选区的文字输入方向
+ * @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);
+ }
- 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();
+ range.select();
+ return true;
+ },
+ queryCommandValue : function() {
+ var node = getObj(this);
+ return node ? node.getAttribute('dir') : 'ltr';
+ }
+ };
+})();
- } 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) {
+// plugins/horizontal.js
+/**
+ * 插入分割线插件
+ * @file
+ * @since 1.2.6.1
+ */
- p.appendChild(li.firstChild);
+/**
+ * 插入分割线
+ * @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();
}
- li.appendChild(p);
- first = p;
}
+ }
- var span = me.document.createElement('span');
-
- range.insertNode(span);
- domUtils.breakParent(span, li);
+ }
+ return true;
+ }
- var nextLi = span.nextSibling;
- first = nextLi.firstChild;
+ },
+ //边界在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;
- 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();
- }
+// plugins/time.js
+/**
+ * 插入时间和日期
+ * @file
+ * @since 1.2.6.1
+ */
- }
+/**
+ * 插入时间,默认格式:12:59:59
+ * @command time
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'time');
+ * ```
+ */
+/**
+ * 插入日期,默认格式:2013-08-30
+ * @command date
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'date');
+ * ```
+ */
+UE.commands['time'] = UE.commands["date"] = {
+ execCommand : function(cmd, format){
+ var date = new Date;
+ function formatTime(date, format) {
+ var hh = ('0' + date.getHours()).slice(-2),
+ ii = ('0' + date.getMinutes()).slice(-2),
+ ss = ('0' + date.getSeconds()).slice(-2);
+ format = format || 'hh:ii:ss';
+ return format.replace(/hh/ig, hh).replace(/ii/ig, ii).replace(/ss/ig, ss);
+ }
+ function formatDate(date, format) {
+ var yyyy = ('000' + date.getFullYear()).slice(-4),
+ yy = yyyy.slice(-2),
+ mm = ('0' + (date.getMonth()+1)).slice(-2),
+ dd = ('0' + date.getDate()).slice(-2);
+ format = format || 'yyyy-mm-dd';
+ return format.replace(/yyyy/ig, yyyy).replace(/yy/ig, yy).replace(/mm/ig, mm).replace(/dd/ig, dd);
}
- 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);
+ this.execCommand('insertHtml',cmd == "time" ? formatTime(date, format):formatDate(date, format) );
+ }
+};
- 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;
+// plugins/rowspacing.js
+/**
+ * 段前段后间距插件
+ * @file
+ * @since 1.2.6.1
+ */
- }
- //trace:980
+/**
+ * 设置段间距
+ * @command rowspacing
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @param { String } value 段间距的值,以px为单位
+ * @param { String } dir 间距位置,top或bottom,分别表示段前和段后
+ * @example
+ * ```javascript
+ * editor.execCommand( 'rowspacing', '10', 'top' );
+ * ```
+ */
- 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{
+UE.plugins['rowspacing'] = function(){
+ var me = this;
+ me.setOpt({
+ 'rowspacingtop':['5', '10', '15', '20', '25'],
+ 'rowspacingbottom':['5', '10', '15', '20', '25']
- while(li.firstChild){
- parentList.parentNode.insertBefore(li.firstChild,parentList);
- }
+ });
+ 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;
- 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;
- }
- }
+// plugins/lineheight.js
+/**
+ * 设置行内间距
+ * @file
+ * @since 1.2.6.1
+ */
+UE.plugins['lineheight'] = function(){
+ var me = this;
+ me.setOpt({'lineheight':['1', '1.5','1.75','2', '3', '4', '5']});
+ /**
+ * 行距
+ * @command lineheight
+ * @method execCommand
+ * @param { String } cmdName 命令字符串
+ * @param { String } value 传入的行高值, 该值是当前字体的倍数, 例如: 1.5, 1.75
+ * @example
+ * ```javascript
+ * editor.execCommand( 'lineheight', 1.5);
+ * ```
+ */
+ /**
+ * 查询当前选区内容的行高大小
+ * @command lineheight
+ * @method queryCommandValue
+ * @param { String } cmd 命令字符串
+ * @return { String } 返回当前行高大小
+ * @example
+ * ```javascript
+ * editor.queryCommandValue( 'lineheight' );
+ * ```
+ */
+ me.commands['lineheight'] = {
+ execCommand : function( cmdName,value ) {
+ this.execCommand('paragraph','p',{style:'line-height:'+ (value == "1" ? "normal" : value + 'em') });
+ return true;
+ },
+ queryCommandValue : function() {
+ var pN = domUtils.filterNodeList(this.selection.getStartElementPath(),function(node){return domUtils.isBlockElm(node)});
+ if(pN){
+ var value = domUtils.getComputedStyle(pN,'line-height');
+ return value == 'normal' ? 1 : value.replace(/[^\d.]*/ig,"");
}
-
}
- });
+ };
+};
- 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)
- }
- }
+
+
+
+// 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'
});
- //处理tab键
- me.addListener('tabkeydown',function(){
- var range = me.selection.getRange();
+ /**
+ * 插入代码
+ * @command insertcode
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @param { String } lang 插入代码的语言
+ * @example
+ * ```javascript
+ * editor.execCommand( 'insertcode', 'javascript' );
+ * ```
+ */
- //控制级数
- 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;
+ /**
+ * 如果选区所在位置是插入插入代码区域,返回代码的语言
+ * @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 += ' '
+ }
+ }
+
+ }
+
+ });
}
- if(levelNum >= me.options.maxListLevel){
- return true;
+ 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;
}
- //只以开始为准
- //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;
+ 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));
}
- }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;
+ 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;
}
}
- 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;
+ 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]
}
- 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;
+
+ }
+ 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]
}
- current = li;
+
}
- adjustList(list,list.tagName.toLowerCase(),currentStyle);
- current = li;
+
+ str = me.document.createTextNode(str);
+ rng.insertNode(str).setStartAfter(str);
}
+ rng.collapse(true).select();
}
- me.fireEvent('contentchange');
- range.moveToBookmark(bk).select();
- return true;
+
+
}
+ me.fireEvent('saveScene');
+ 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' );
- * ```
- */
+ 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){
- /**
- * 无序列表,与“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' );
- * ```
- */
+ }else{
+ if(!rng.collapsed){
+ var bk = rng.createBookmark();
+ var start = bk.start.previousSibling;
- me.commands['insertorderedlist'] =
- me.commands['insertunorderedlist'] = {
- execCommand:function (command, style) {
+ while(start){
+ if(pre.firstChild === start && !domUtils.isBr(start)){
+ pre.insertBefore(me.document.createTextNode(' '),start);
- 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;
+ break;
+ }
+ if(domUtils.isBr(start)){
+ pre.insertBefore(me.document.createTextNode(' '),start.nextSibling);
- if (start || end) {
- start && (startParent = start.parentNode);
- if (!bko.end) {
- end = start;
+ break;
+ }
+ start = start.previousSibling;
}
- end && (endParent = end.parentNode);
+ var end = bk.end;
+ start = bk.start.nextSibling;
+ if(pre.firstChild === bk.start){
+ pre.insertBefore(me.document.createTextNode(' '),start.nextSibling)
- 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);
+ }
+ while(start && start !== end){
+ if(domUtils.isBr(start) && start.nextSibling){
+ if(start.nextSibling === end){
+ break;
}
- frag.appendChild(tmp);
+ pre.insertBefore(me.document.createTextNode(' '),start.nextSibling)
}
- 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);
- }
- }
+ start = start.nextSibling;
+ }
+ rng.moveToBookmark(bk).select();
+ }else{
+ var tmpNode = me.document.createTextNode(' ');
+ rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true).select(true);
+ }
+ }
- }
- 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;
+ 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();
}
- tmpfrag.appendChild(start.firstChild);
- }
- if (!hasBlock) {
- var tmpP = me.document.createElement('p');
- tmpP.appendChild(tmpfrag);
- frag.appendChild(tmpP);
- } else {
- frag.appendChild(tmpfrag);
+ }else{
+ htmlstr += cn.data
}
- domUtils.remove(start);
+ })
+ if(!/\n$/.test(htmlstr)){
+ htmlstr += '\n';
}
-
- start = tmp;
- }
- startParent.parentNode.insertBefore(frag, startParent.nextSibling);
- if (domUtils.isEmptyNode(startParent)) {
- range.setStartBefore(startParent);
- domUtils.remove(startParent);
- } else {
- range.setStartAfter(startParent);
}
- modifyStart = 1;
+ }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,' '))));
- 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);
+ }else{
+ frag.appendChild(me.document.createTextNode(utils.html( cn.data.replace(/ /g,' '))));
+
}
- domUtils.remove(start);
+ })
+ if(frag.lastChild.nodeName != 'BR'){
+ frag.appendChild(me.document.createElement('br'))
}
- 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;
+ }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();
- if (!modifyStart) {
- range.setStartBefore(me.document.getElementById(bko.start));
+ }
+
+ 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 (bko.end && !modifyEnd) {
- range.setEndAfter(me.document.getElementById(bko.end));
+ if(last === start || rng.startContainer === pre && rng.startOffset == pre.childNodes.length){
+ me.execCommand('insertparagraph');
+ domUtils.preventDefault(evt)
}
- range.enlarge(true, function (node) {
- return notExchange[node.tagName];
- });
- frag = me.document.createDocumentFragment();
+ }
+ }
+ });
+ //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;
+ }
+ })
+};
- 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)) {
+// plugins/cleardoc.js
+/**
+ * 清空文档插件
+ * @file
+ * @since 1.2.6.1
+ */
- 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;
+/**
+ * 清空文档
+ * @command cleardoc
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * //editor 是编辑器实例
+ * editor.execCommand('cleardoc');
+ * ```
+ */
- }
- tmpNode = current;
- tmpRange.setStartBefore(current);
+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);
- 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');
+// plugins/anchor.js
+/**
+ * 锚点插件,为UEditor提供插入锚点支持
+ * @file
+ * @since 1.2.6.1
+ */
+UE.plugin.register('anchor', function (){
- 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();
+ return {
+ bindEvents:{
+ 'ready':function(){
+ utils.cssRule('anchor',
+ '.anchorclass{background: url(\''
+ + this.options.themePath
+ + this.options.theme +'/images/anchor.gif\') no-repeat scroll left center transparent;cursor: auto;display: inline-block;height: 16px;width: 15px;}',
+ this.document);
+ }
+ },
+ outputRule: function(root){
+ utils.each(root.getNodesByTagName('img'),function(a){
+ var val;
+ if(val = a.getAttr('anchorname')){
+ a.tagName = 'a';
+ a.setAttr({
+ anchorname : '',
+ name : val,
+ 'class' : ''
+ })
+ }
+ })
+ },
+ inputRule:function(root){
+ utils.each(root.getNodesByTagName('a'),function(a){
+ var val;
+ if((val = a.getAttr('name')) && !a.getAttr('href')){
+ a.tagName = 'img';
+ a.setAttr({
+ anchorname :a.getAttr('name'),
+ 'class' : 'anchorclass'
+ });
+ a.setAttr('name')
- },
- 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;
- }
- };
+ },
+ commands:{
+ /**
+ * 插入锚点
+ * @command anchor
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @param { String } name 锚点名称字符串
+ * @example
+ * ```javascript
+ * //editor 是编辑器实例
+ * editor.execCommand('anchor', 'anchor1');
+ * ```
+ */
+ 'anchor':{
+ execCommand:function (cmd, name) {
+ var range = this.selection.getRange(),img = range.getClosedNode();
+ if (img && img.getAttribute('anchorname')) {
+ if (name) {
+ img.setAttribute('anchorname', name);
+ } else {
+ range.setStartBefore(img).setCursor();
+ domUtils.remove(img);
+ }
+ } else {
+ if (name) {
+ //只在选区的开始插入
+ var anchor = this.document.createElement('img');
+ range.collapse(true);
+ domUtils.setAttributes(anchor,{
+ 'anchorname':name,
+ 'class':'anchorclass'
+ });
+ range.insertNode(anchor).setStartAfter(anchor).setCursor(false,true);
+ }
+ }
+ }
+ }
+ }
+ }
+});
+
+
+// plugins/wordcount.js
+///import core
+///commands 字数统计
+///commandsName WordCount,wordCount
+///commandsTitle 字数统计
+/*
+ * Created by JetBrains WebStorm.
+ * User: taoqili
+ * Date: 11-9-7
+ * Time: 下午8:18
+ * To change this template use File | Settings | File Templates.
+ */
+
+UE.plugins['wordcount'] = function(){
+ var me = this;
+ me.setOpt('wordCount',true);
+ me.addListener('contentchange',function(){
+ me.fireEvent('wordcount');
+ });
+ var timer;
+ me.addListener('ready',function(){
+ var me = this;
+ domUtils.on(me.body,"keyup",function(evt){
+ var code = evt.keyCode||evt.which,
+ //忽略的按键,ctr,alt,shift,方向键
+ ignores = {"16":1,"18":1,"20":1,"37":1,"38":1,"39":1,"40":1};
+ if(code in ignores) return;
+ clearTimeout(timer);
+ timer = setTimeout(function(){
+ me.fireEvent('wordcount');
+ },200)
+ })
+ });
};
-
-
-// plugins/source.js
+
+// 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 (){
- var sourceEditors = {
- textarea: function (editor, holder){
- var textarea = holder.ownerDocument.createElement('textarea');
- textarea.style.cssText = 'position:absolute;resize:none;width:100%;height:100%;border:0;padding:0;margin:0;overflow-y:auto;';
- // todo: IE下只有onresize属性可用... 很纠结
- if (browser.ie && browser.version < 8) {
- textarea.style.width = holder.offsetWidth + 'px';
- textarea.style.height = holder.offsetHeight + 'px';
- holder.onresize = function (){
- textarea.style.width = holder.offsetWidth + 'px';
- textarea.style.height = holder.offsetHeight + 'px';
- };
- }
- holder.appendChild(textarea);
- return {
- setContent: function (content){
- textarea.value = content;
- },
- getContent: function (){
- return textarea.value;
- },
- select: function (){
- var range;
- if (browser.ie) {
- range = textarea.createTextRange();
- range.collapse(true);
- range.select();
- } else {
- //todo: chrome下无法设置焦点
- textarea.setSelectionRange(0, 0);
- textarea.focus();
- }
- },
- dispose: function (){
- holder.removeChild(textarea);
- // todo
- holder.onresize = null;
- textarea = null;
- holder = null;
- }
- };
- },
- codemirror: function (editor, holder){
-
- var codeEditor = window.CodeMirror(holder, {
- mode: "text/html",
- tabMode: "indent",
- lineNumbers: true,
- lineWrapping:true
- });
- var dom = codeEditor.getWrapperElement();
- dom.style.cssText = 'position:absolute;left:0;top:0;width:100%;height:100%;font-family:consolas,"Courier new",monospace;font-size:13px;';
- codeEditor.getScrollerElement().style.cssText = 'position:absolute;left:0;top:0;width:100%;height:100%;';
- codeEditor.refresh();
- return {
- getCodeMirror:function(){
- return codeEditor;
- },
- setContent: function (content){
- codeEditor.setValue(content);
- },
- getContent: function (){
- return codeEditor.getValue();
- },
- select: function (){
- codeEditor.focus();
- },
- dispose: function (){
- holder.removeChild(dom);
- dom = null;
- codeEditor = null;
- }
- };
- }
- };
-
- UE.plugins['source'] = function (){
- var me = this;
- var opt = this.options;
- var sourceMode = false;
- var sourceEditor;
- var orgSetContent;
- opt.sourceEditor = browser.ie ? 'textarea' : (opt.sourceEditor || 'codemirror');
+ function fillNode(node){
+ if(domUtils.isEmptyBlock(node)){
+ var firstChild = node.firstChild,tmpNode;
- me.setOpt({
- sourceEditorFirst:false
- });
- function createSourceEditor(holder){
- return sourceEditors[opt.sourceEditor == 'codemirror' && window.CodeMirror ? 'codemirror' : 'textarea'](me, holder);
+ while(firstChild && firstChild.nodeType == 1 && domUtils.isEmptyBlock(firstChild)){
+ tmpNode = firstChild;
+ firstChild = firstChild.firstChild;
+ }
+ !tmpNode && (tmpNode = node);
+ domUtils.fillNode(me.document,tmpNode);
}
+ }
+ //分页符样式添加
- 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.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);
+ }
+ })
- 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;
- }
+ /**
+ * 插入分页符
+ * @command pagebreak
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @remind 在表格中插入分页符会把表格切分成两部分
+ * @remind 获取编辑器内的数据时, 编辑器会把分页符转换成“_ueditor_page_break_tag_”字符串,
+ * 以便于提交数据到服务器端后处理分页。
+ * @example
+ * ```javascript
+ * editor.execCommand( 'pagebreak'); //插入一个hr标签,带有样式类名pagebreak
+ * ```
+ */
- bakCssText = me.iframe.style.cssText;
- me.iframe.style.cssText += 'position:absolute;left:-32768px;top:-32768px;';
+ 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);
- 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,' '))
+ } else {
+ pN.parentNode.insertBefore(hr, pN);
+ parents = domUtils.findParents(hr);
- }
}
- });
-
- 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){}
- });
- });
+ pN = parents[1];
+ if (hr !== pN) {
+ domUtils.breakParent(hr, pN);
- //重置getContent,源码模式下取值也能是最新的数据
- oldGetContent = me.getContent;
- me.getContent = function (){
- return sourceEditor.getContent() || '' + (browser.ie ? '' : ' ')+' ';
- };
- } else {
- me.iframe.style.cssText = bakCssText;
- var cont = sourceEditor.getContent() || '' + (browser.ie ? '' : ' ')+' ';
- //处理掉block节点前后的空格,有可能会误命中,暂时不考虑
- cont = cont.replace(new RegExp('[\\r\\t\\n ]*<\/?(\\w+)\\s*(?:[^>]*)>','g'), function(a,b){
- if(b && !dtd.$inlineWithA[b.toLowerCase()]){
- return a.replace(/(^[\n\r\t ]*)|([\n\r\t ]*$)/g,'');
}
- return a.replace(/(^[\n\r\t]*)|([\n\r\t]*$)/g,'')
- });
+ //table要重写绑定一下拖拽
+ me.fireEvent('afteradjusttable',me.document);
+ }
- me.setContent = orgSetContent;
+ } else {
- me.setContent(cont);
- sourceEditor.dispose();
- sourceEditor = null;
- //还原getContent方法
- me.getContent = oldGetContent;
- var first = me.body.firstChild;
- //trace:1106 都删除空了,下边会报错,所以补充一个p占位
- if(!first){
- me.body.innerHTML = ''+(browser.ie?'':' ')+' ';
- first = me.body.firstChild;
+ 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);
- //要在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);
+ 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);
+ }
- 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);
- });
+ 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{
- //ie下有可能报错,比如在代码顶头的情况
- try{
- me.selection.getRange().moveToAddress(bakAddress).select(true);
- }catch(e){}
-
+ fillNode(nextNode);
}
+ range.setEndAfter(hr).collapse(false);
}
- 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"){
+ range.select(true);
- 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
+// plugins/wordimage.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);
+///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);
}
-
- if (me.undoManger && doSave) {
- me.undoManger.save();
+ 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;
+ }
}
- }
- //没有站位符,会出现多行的问题
- 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;
+ return -1;
+ },
+ notNeedUndo:true
}
- 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;
+ },
+ inputRule : function (root) {
+ utils.each(root.getNodesByTagName('img'), function (img) {
+ var attrs = img.attrs,
+ flag = parseInt(attrs.width) < 128 || parseInt(attrs.height) < 43,
+ opt = me.options,
+ src = opt.UEDITOR_HOME_URL + 'themes/default/images/spacer.gif';
+ if (attrs['src'] && /^(?:(file:\/+))/.test(attrs['src'])) {
+ img.setAttr({
+ width:attrs.width,
+ height:attrs.height,
+ alt:attrs.alt,
+ word_img: attrs.src,
+ src:src,
+ 'style':'background:url(' + ( flag ? opt.themePath + opt.theme + '/images/word.gif' : opt.langPath + opt.lang + '/images/localimage.png') + ') no-repeat center center;border:1px solid #ddd'
+ })
}
- }
- 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, ' ');
+// plugins/dragdrop.js
+UE.plugins['dragdrop'] = function (){
- if (browser.gecko) {
- range = me.selection.getRange();
- start = domUtils.findParentByTagName(range.startContainer, 'p', true);
- start && domUtils.removeDirtyAttr(start);
- }
+ 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'){
- } else {
- hTag = start.tagName;
- start.tagName.toLowerCase() == 'p' && browser.gecko && domUtils.removeDirtyAttr(start);
+ var pre = node.previousSibling,next;
+ while(next = node.nextSibling){
+ if(next.nodeType == 1 && next.tagName == 'SPAN' && !next.firstChild){
+ domUtils.remove(next)
+ }else{
+ break;
}
-
}
- } 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();
+ 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);
}
-
- } 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);
+ if(pre && pre.tagName == 'P' && domUtils.isEmptyBlock(pre)){
+ domUtils.remove(pre)
}
- range.setCursor();
+ 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/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);
+// plugins/undo.js
+/**
+ * undo redo
+ * @file
+ * @since 1.2.6.1
+ */
+
+/**
+ * 撤销上一次执行的命令
+ * @command undo
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'undo' );
+ * ```
+ */
+
+/**
+ * 重做上一次执行的命令
+ * @command redo
+ * @method execCommand
+ * @param { String } cmd 命令字符串
+ * @example
+ * ```javascript
+ * editor.execCommand( 'redo' );
+ * ```
+ */
+
+UE.plugins['undo'] = function () {
+ var saveSceneTimer;
+ var me = this,
+ maxUndoCount = me.options.maxUndoCount || 20,
+ maxInputCount = me.options.maxInputCount || 20,
+ fillchar = new RegExp(domUtils.fillChar + '|<\/hr>', 'gi');// ie会产生多余的
+ var noNeedFillCharTags = {
+ ol:1,ul:1,table:1,tbody:1,tr:1,body:1
+ };
+ var orgState = me.options.autoClearEmptyNode;
+ function compareAddr(indexA, indexB) {
+ if (indexA.length != indexB.length)
+ return 0;
+ for (var i = 0, l = indexA.length; i < l; i++) {
+ if (indexA[i] != indexB[i])
+ return 0
+ }
+ return 1;
+ }
+
+ function compareRangeAddress(rngAddrA, rngAddrB) {
+ if (rngAddrA.collapsed != rngAddrB.collapsed) {
+ return 0;
+ }
+ if (!compareAddr(rngAddrA.startAddress, rngAddrB.startAddress) || !compareAddr(rngAddrA.endAddress, rngAddrB.endAddress)) {
+ return 0;
+ }
+ return 1;
+ }
+
+ function UndoManager() {
+ this.list = [];
+ this.index = 0;
+ this.hasUndo = false;
+ this.hasRedo = false;
+ this.undo = function () {
+ if (this.hasUndo) {
+ if (!this.list[this.index - 1] && this.list.length == 1) {
+ this.reset();
+ return;
+ }
+ while (this.list[this.index].content == this.list[this.index - 1].content) {
+ this.index--;
+ if (this.index == 0) {
+ return this.restore(0);
+ }
}
+ this.restore(--this.index);
}
- 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;
+ };
+ 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);
}
- }
+ };
- //处理backspace
- if (keyCode == keymap.Backspace) {
- rng = me.selection.getRange();
- collapsed = rng.collapsed;
- if(me.fireEvent('delkeydown',evt)){
- return;
+ 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);
+ }
+ })
}
- 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)
- }
- }
+ try{
+ var rng = new dom.Range(me.document).moveToAddress(scene.address);
+ rng.select(noNeedFillCharTags[rng.startContainer.nodeName.toLowerCase()]);
+ }catch(e){}
- //解决选中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;
- }
+ 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];
- }
- //处理tab键的逻辑
- if (keyCode == keymap.Tab) {
- //不处理以下标签
- var excludeTagNameForTabKey = {
- 'ol' : 1,
- 'ul' : 1,
- 'table':1
- };
- //处理组件里的tab按下事件
- if(me.fireEvent('tabkeydown',evt)){
- domUtils.preventDefault(evt);
+ if(lastScene && lastScene.content != currentScene.content){
+ me.trigger('contentchange')
+ }
+ //内容相同位置相同不存
+ if (lastScene && lastScene.content == currentScene.content &&
+ ( notCompareRange ? 1 : compareRangeAddress(lastScene.address, currentScene.address) )
+ ) {
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;
+ this.list = this.list.slice(0, this.index + 1);
+ this.list.push(currentScene);
+ //如果大于最大数量了,就把最前的剔除
+ if (this.list.length > maxUndoCount) {
+ this.list.shift();
}
- 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()]
+ this.index = this.list.length - 1;
+ this.clearKey();
+ //跟新undo/redo状态
+ this.update();
- };
- //普通的情况
- 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)
+ };
+ 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();
}
- //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();
+ });
+ 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 || (evt.shiftKey && /\w/.test(evt.key))) {
+ 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,
- rng,me = this;
- if(keyCode == keymap.Backspace){
- if(me.fireEvent('delkeyup')){
+ 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;
}
- 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;
- }
- }
+ }
+ });
+ //扩展实例,添加关闭和开启命令undo
+ me.stopCmdUndo = function(){
+ me.__hasEnterExecCommand = true;
+ };
+ me.startCmdUndo = function(){
+ me.__hasEnterExecCommand = false;
+ }
+};
+
+
+// plugins/copy.js
+UE.plugin.register('copy', function () {
+
+ var me = this;
+
+ function initZeroClipboard() {
+
+ ZeroClipboard.config({
+ debug: false,
+ swfPath: me.options.UEDITOR_HOME_URL + 'third-party/zeroclipboard/ZeroClipboard.swf'
+ });
+
+ var client = me.zeroclipboard = new ZeroClipboard();
+
+ // 复制内容
+ client.on('copy', function (e) {
+ var client = e.client,
+ rng = me.selection.getRange(),
+ div = document.createElement('div');
+
+ div.appendChild(rng.cloneContents());
+ client.setText(div.innerText || div.textContent);
+ client.setHtml(div.innerHTML);
+ rng.select();
+ });
+ // hover事件传递到target
+ client.on('mouseover mouseout', function (e) {
+ var target = e.target;
+ if (e.type == 'mouseover') {
+ domUtils.addClass(target, 'edui-state-hover');
+ } else if (e.type == 'mouseout') {
+ domUtils.removeClasses(target, 'edui-state-hover');
+ }
+ });
+ // flash加载不成功
+ client.on('wrongflash noflash', function () {
+ ZeroClipboard.destroy();
+ });
+ }
+
+ return {
+ bindEvents: {
+ 'ready': function () {
+ if (!browser.ie) {
+ if (window.ZeroClipboard) {
+ initZeroClipboard();
+ } else {
+ utils.loadFile(document, {
+ src: me.options.UEDITOR_HOME_URL + "third-party/zeroclipboard/ZeroClipboard.js",
+ tag: "script",
+ type: "text/javascript",
+ defer: "defer"
+ }, function () {
+ initZeroClipboard();
+ });
}
}
- //处理当删除到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()
+ },
+ commands: {
+ 'copy': {
+ execCommand: function (cmd) {
+ if (!me.document.execCommand('copy')) {
+ alert(me.getLang('copymsg'));
+ }
}
-
}
}
+ }
+});
- })
-};
-
-// plugins/fiximgclick.js
-///import core
-///commands 修复chrome下图片不能点击的问题,出现八个角可改变大小
-///commandsName FixImgClick
-///commandsTitle 修复chrome下图片不能点击的问题,出现八个角可改变大小
-//修复chrome下图片不能点击的问题,出现八个角可改变大小
-
-UE.plugins['fiximgclick'] = (function () {
-
- var elementUpdated = false;
- function Scale() {
- this.editor = null;
- this.resizer = null;
- this.cover = null;
- this.doc = document;
- this.prePos = {x: 0, y: 0};
- this.startPos = {x: 0, y: 0};
- }
-
- (function () {
- var rect = [
- //[left, top, width, height]
- [0, 0, -1, -1],
- [0, 0, 0, -1],
- [0, 0, 1, -1],
- [0, 0, -1, 0],
- [0, 0, 1, 0],
- [0, 0, -1, 1],
- [0, 0, 0, 1],
- [0, 0, 1, 1]
- ];
-
- Scale.prototype = {
- init: function (editor) {
- var me = this;
- me.editor = editor;
- me.startPos = this.prePos = {x: 0, y: 0};
- me.dragId = -1;
-
- var hands = [],
- cover = me.cover = document.createElement('div'),
- resizer = me.resizer = document.createElement('div');
-
- cover.id = me.editor.ui.id + '_imagescale_cover';
- cover.style.cssText = 'position:absolute;display:none;z-index:' + (me.editor.options.zIndex) + ';filter:alpha(opacity=0); opacity:0;background:#CCC;';
- domUtils.on(cover, 'mousedown click', function () {
- me.hide();
- });
-
- for (i = 0; i < 8; i++) {
- hands.push('');
- }
- resizer.id = me.editor.ui.id + '_imagescale';
- resizer.className = 'edui-editor-imagescale';
- resizer.innerHTML = hands.join('');
- resizer.style.cssText += ';display:none;border:1px solid #3b77ff;z-index:' + (me.editor.options.zIndex) + ';';
-
- me.editor.ui.getDom().appendChild(cover);
- me.editor.ui.getDom().appendChild(resizer);
-
- me.initStyle();
- me.initEvents();
- },
- initStyle: function () {
- utils.cssRule('imagescale', '.edui-editor-imagescale{display:none;position:absolute;border:1px solid #38B2CE;cursor:hand;-webkit-box-sizing: content-box;-moz-box-sizing: content-box;box-sizing: content-box;}' +
- '.edui-editor-imagescale span{position:absolute;width:6px;height:6px;overflow:hidden;font-size:0px;display:block;background-color:#3C9DD0;}'
- + '.edui-editor-imagescale .edui-editor-imagescale-hand0{cursor:nw-resize;top:0;margin-top:-4px;left:0;margin-left:-4px;}'
- + '.edui-editor-imagescale .edui-editor-imagescale-hand1{cursor:n-resize;top:0;margin-top:-4px;left:50%;margin-left:-4px;}'
- + '.edui-editor-imagescale .edui-editor-imagescale-hand2{cursor:ne-resize;top:0;margin-top:-4px;left:100%;margin-left:-3px;}'
- + '.edui-editor-imagescale .edui-editor-imagescale-hand3{cursor:w-resize;top:50%;margin-top:-4px;left:0;margin-left:-4px;}'
- + '.edui-editor-imagescale .edui-editor-imagescale-hand4{cursor:e-resize;top:50%;margin-top:-4px;left:100%;margin-left:-3px;}'
- + '.edui-editor-imagescale .edui-editor-imagescale-hand5{cursor:sw-resize;top:100%;margin-top:-3px;left:0;margin-left:-4px;}'
- + '.edui-editor-imagescale .edui-editor-imagescale-hand6{cursor:s-resize;top:100%;margin-top:-3px;left:50%;margin-left:-4px;}'
- + '.edui-editor-imagescale .edui-editor-imagescale-hand7{cursor:se-resize;top:100%;margin-top:-3px;left:100%;margin-left:-3px;}');
- },
- initEvents: function () {
- var me = this;
-
- me.startPos.x = me.startPos.y = 0;
- me.isDraging = false;
- },
- _eventHandler: function (e) {
- var me = this;
- switch (e.type) {
- case 'mousedown':
- var hand = e.target || e.srcElement, hand;
- if (hand.className.indexOf('edui-editor-imagescale-hand') != -1 && me.dragId == -1) {
- me.dragId = hand.className.slice(-1);
- me.startPos.x = me.prePos.x = e.clientX;
- me.startPos.y = me.prePos.y = e.clientY;
- domUtils.on(me.doc,'mousemove', me.proxy(me._eventHandler, me));
- }
- break;
- case 'mousemove':
- if (me.dragId != -1) {
- me.updateContainerStyle(me.dragId, {x: e.clientX - me.prePos.x, y: e.clientY - me.prePos.y});
- me.prePos.x = e.clientX;
- me.prePos.y = e.clientY;
- elementUpdated = true;
- me.updateTargetElement();
-
- }
- break;
- case 'mouseup':
- if (me.dragId != -1) {
- me.updateContainerStyle(me.dragId, {x: e.clientX - me.prePos.x, y: e.clientY - me.prePos.y});
- me.updateTargetElement();
- if (me.target.parentNode) me.attachTo(me.target);
- me.dragId = -1;
- }
- domUtils.un(me.doc,'mousemove', me.proxy(me._eventHandler, me));
- //修复只是点击挪动点,但没有改变大小,不应该触发contentchange
- if(elementUpdated){
- elementUpdated = false;
- me.editor.fireEvent('contentchange');
- }
-
- break;
- default:
- break;
- }
- },
- updateTargetElement: function () {
- var me = this;
- domUtils.setStyles(me.target, {
- 'width': me.resizer.style.width,
- 'height': me.resizer.style.height
- });
- me.target.width = parseInt(me.resizer.style.width);
- me.target.height = parseInt(me.resizer.style.height);
- me.attachTo(me.target);
- },
- updateContainerStyle: function (dir, offset) {
- var me = this,
- dom = me.resizer, tmp;
-
- if (rect[dir][0] != 0) {
- tmp = parseInt(dom.style.left) + offset.x;
- dom.style.left = me._validScaledProp('left', tmp) + 'px';
- }
- if (rect[dir][1] != 0) {
- tmp = parseInt(dom.style.top) + offset.y;
- dom.style.top = me._validScaledProp('top', tmp) + 'px';
- }
- if (rect[dir][2] != 0) {
- tmp = dom.clientWidth + rect[dir][2] * offset.x;
- dom.style.width = me._validScaledProp('width', tmp) + 'px';
- }
- if (rect[dir][3] != 0) {
- tmp = dom.clientHeight + rect[dir][3] * offset.y;
- dom.style.height = me._validScaledProp('height', tmp) + 'px';
- }
- },
- _validScaledProp: function (prop, value) {
- var ele = this.resizer,
- wrap = document;
-
- value = isNaN(value) ? 0 : value;
- switch (prop) {
- case 'left':
- return value < 0 ? 0 : (value + ele.clientWidth) > wrap.clientWidth ? wrap.clientWidth - ele.clientWidth : value;
- case 'top':
- return value < 0 ? 0 : (value + ele.clientHeight) > wrap.clientHeight ? wrap.clientHeight - ele.clientHeight : value;
- case 'width':
- return value <= 0 ? 1 : (value + ele.offsetLeft) > wrap.clientWidth ? wrap.clientWidth - ele.offsetLeft : value;
- case 'height':
- return value <= 0 ? 1 : (value + ele.offsetTop) > wrap.clientHeight ? wrap.clientHeight - ele.offsetTop : value;
- }
- },
- hideCover: function () {
- this.cover.style.display = 'none';
- },
- showCover: function () {
- var me = this,
- editorPos = domUtils.getXY(me.editor.ui.getDom()),
- iframePos = domUtils.getXY(me.editor.iframe);
-
- domUtils.setStyles(me.cover, {
- 'width': me.editor.iframe.offsetWidth + 'px',
- 'height': me.editor.iframe.offsetHeight + 'px',
- 'top': iframePos.y - editorPos.y + 'px',
- 'left': iframePos.x - editorPos.x + 'px',
- 'position': 'absolute',
- 'display': ''
- })
- },
- show: function (targetObj) {
- var me = this;
- me.resizer.style.display = 'block';
- if(targetObj) me.attachTo(targetObj);
-
- domUtils.on(this.resizer, 'mousedown', me.proxy(me._eventHandler, me));
- domUtils.on(me.doc, 'mouseup', me.proxy(me._eventHandler, me));
-
- me.showCover();
- me.editor.fireEvent('afterscaleshow', me);
- me.editor.fireEvent('saveScene');
- },
- hide: function () {
- var me = this;
- me.hideCover();
- me.resizer.style.display = 'none';
-
- domUtils.un(me.resizer, 'mousedown', me.proxy(me._eventHandler, me));
- domUtils.un(me.doc, 'mouseup', me.proxy(me._eventHandler, me));
- me.editor.fireEvent('afterscalehide', me);
- },
- proxy: function( fn, context ) {
- return function(e) {
- return fn.apply( context || this, arguments);
- };
- },
- attachTo: function (targetObj) {
- var me = this,
- target = me.target = targetObj,
- resizer = this.resizer,
- imgPos = domUtils.getXY(target),
- iframePos = domUtils.getXY(me.editor.iframe),
- editorPos = domUtils.getXY(resizer.parentNode);
-
- domUtils.setStyles(resizer, {
- 'width': target.width + 'px',
- 'height': target.height + 'px',
- 'left': iframePos.x + imgPos.x - me.editor.document.body.scrollLeft - editorPos.x - parseInt(resizer.style.borderLeftWidth) + 'px',
- 'top': iframePos.y + imgPos.y - me.editor.document.body.scrollTop - editorPos.y - parseInt(resizer.style.borderTopWidth) + 'px'
- });
- }
- }
- })();
-
- return function () {
- var me = this,
- imageScale;
-
- me.setOpt('imageScaleEnabled', true);
-
- if ( !browser.ie && me.options.imageScaleEnabled) {
- me.addListener('click', function (type, e) {
-
- var range = me.selection.getRange(),
- img = range.getClosedNode();
-
- if (img && img.tagName == 'IMG' && me.body.contentEditable!="false") {
-
- if (img.className.indexOf("edui-faked-music") != -1 ||
- img.getAttribute("anchorname") ||
- domUtils.hasClass(img, 'loadingclass') ||
- domUtils.hasClass(img, 'loaderrorclass')) { return }
-
- if (!imageScale) {
- imageScale = new Scale();
- imageScale.init(me);
- me.ui.getDom().appendChild(imageScale.resizer);
-
- var _keyDownHandler = function (e) {
- imageScale.hide();
- if(imageScale.target) me.selection.getRange().selectNode(imageScale.target).select();
- }, _mouseDownHandler = function (e) {
- var ele = e.target || e.srcElement;
- if (ele && (ele.className===undefined || ele.className.indexOf('edui-editor-imagescale') == -1)) {
- _keyDownHandler(e);
- }
- }, timer;
-
- me.addListener('afterscaleshow', function (e) {
- me.addListener('beforekeydown', _keyDownHandler);
- me.addListener('beforemousedown', _mouseDownHandler);
- domUtils.on(document, 'keydown', _keyDownHandler);
- domUtils.on(document,'mousedown', _mouseDownHandler);
- me.selection.getNative().removeAllRanges();
- });
- me.addListener('afterscalehide', function (e) {
- me.removeListener('beforekeydown', _keyDownHandler);
- me.removeListener('beforemousedown', _mouseDownHandler);
- domUtils.un(document, 'keydown', _keyDownHandler);
- domUtils.un(document,'mousedown', _mouseDownHandler);
- var target = imageScale.target;
- if (target.parentNode) {
- me.selection.getRange().selectNode(target).select();
- }
- });
- //TODO 有iframe的情况,mousedown不能往下传。。
- domUtils.on(imageScale.resizer, 'mousedown', function (e) {
- me.selection.getNative().removeAllRanges();
- var ele = e.target || e.srcElement;
- if (ele && ele.className.indexOf('edui-editor-imagescale-hand') == -1) {
- timer = setTimeout(function () {
- imageScale.hide();
- if(imageScale.target) me.selection.getRange().selectNode(ele).select();
- }, 200);
- }
- });
- domUtils.on(imageScale.resizer, 'mouseup', function (e) {
- var ele = e.target || e.srcElement;
- if (ele && ele.className.indexOf('edui-editor-imagescale-hand') == -1) {
- clearTimeout(timer);
- }
- });
- }
- imageScale.show(img);
- } else {
- if (imageScale && imageScale.resizer.style.display != 'none') imageScale.hide();
- }
- });
- }
-
- if (browser.webkit) {
- me.addListener('click', function (type, e) {
- if (e.target.tagName == 'IMG' && me.body.contentEditable!="false") {
- var range = new dom.Range(me.document);
- range.selectNode(e.target).select();
- }
- });
- }
- }
-})();
-
-// plugins/autolink.js
+// plugins/paste.js
///import core
-///commands 为非ie浏览器自动添加a标签
-///commandsName AutoLink
-///commandsTitle 自动增加链接
+///import plugins/inserthtml.js
+///import plugins/undo.js
+///import plugins/serialize.js
+///commands 粘贴
+///commandsName PastePlain
+///commandsTitle 纯文本粘贴模式
/**
- * @description 为非ie浏览器自动添加a标签
+ * @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);
-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) {
+ 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 sel = me.selection.getNative(),
- range = sel.getRangeAt(0).cloneRange(),
- offset,
- charCode;
+ var me = this;
- 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;
- }
+ me.setOpt({
+ retainOnlyLabelPasted : false
+ });
- do{
- if (range.startOffset == 0) {
- start = range.startContainer.previousSibling;
+ var txtContent, htmlContent, address;
- 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);
+ 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 {
- 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;
+ return '<' + b + tagName + ' ' + utils.trim(attrs) + '>'
+ }
- }
- range.setStart(next,0);
+ });
+ }
+ 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) {
- }
- //range的开始边界已经在a标签里的不再处理
- if(domUtils.findParentByTagName(range.startContainer,'a',true)){
- return;
- }
- var a = me.document.createElement('a'),text = me.document.createTextNode(' '),href;
+ 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);
+ }
- me.undoManger && me.undoManger.save();
- a.appendChild(range.extractContents());
- a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g,'');
- href = a.getAttribute("href").replace(new RegExp(domUtils.fillChar,'g'),'');
- href = /^(?:https?:\/\/)/ig.test(href) ? href : "http://"+ href;
- a.setAttribute('_src',utils.html(href));
- a.href = utils.html(href);
+ var metas = div.querySelectorAll('meta');
+ for (var i = 0, ci; ci = metas[i++];) {
+ domUtils.remove(ci);
+ }
- 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();
- }
+ var brs = div.querySelectorAll('br');
+ for (i = 0; ci = brs[i++];) {
+ if (/^apple-/i.test(ci.className)) {
+ domUtils.remove(ci);
}
}
}
- }:{}
- },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 (browser.gecko) {
+ var dirtyNodes = div.querySelectorAll('[_moz_dirty]');
+ for (i = 0; ci = dirtyNodes[i++];) {
+ ci.removeAttribute('_moz_dirty');
+ }
}
- if(node.nodeName == 'A'){
- return node;
+ if (!browser.ie) {
+ var spans = div.querySelectorAll('span.Apple-style-span');
+ for (var i = 0, ci; ci = spans[i++];) {
+ domUtils.remove(ci, true);
+ }
}
- var lastChild = node.lastChild;
- while(lastChild){
- if(lastChild.nodeName == 'A'){
- return lastChild;
+ //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)
}
- if(lastChild.nodeType == 3){
- if(domUtils.isWhitespace(lastChild)){
- lastChild = lastChild.previousSibling;
- continue;
+ utils.each(me.body.querySelectorAll('div'), function (node) {
+ if (domUtils.isEmptyBlock(node)) {
+ domUtils.remove(node,true)
}
- return null
- }
- lastChild = lastChild.lastChild;
+ })
+ }
+ 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);
}
- 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'){
+ 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 == 1){
- var pre = checkIsCludeLink(pre);
- if(pre && !pre.getAttribute('_href')){
- domUtils.remove(pre,true);
- }
+
+ if(pre && pre.nodeType == 3 && new RegExp('^[\n\r\t '+domUtils.fillChar+']*$').test(pre.nodeValue)){
+ range.setStartBefore(pre)
}
}
- }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);
- }
+ if(range.startOffset == 0){
+ range.setStartBefore(range.startContainer);
+ }else{
+ break;
}
- }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)
+ }
+ while (!domUtils.isBody(range.endContainer)
+ ) {
+ var end = range.endContainer;
+ if(end.nodeType == 1){
+ end = end.childNodes[range.endOffset];
+ if(!end){
+ range.setEndAfter(range.endContainer);
+ continue;
+ }
+ var next = end.nextSibling;
+ if(next && next.nodeType == 3 && new RegExp('^[\n\r\t'+domUtils.fillChar+']*$').test(next.nodeValue)){
+ range.setEndAfter(next)
+ }
+ }
+ if(range.endOffset == range.endContainer[range.endContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length){
+ range.setEndAfter(range.endContainer);
+ }else{
+ break;
}
+
}
}
+ range.deleteContents();
+ range.select(true);
+ me.__hasEnterExecCommand = true;
+ var html = htmlContent;
+ if (plainType === 2 ) {
+ html = getPureHtml(html);
+ } else if (plainType) {
+ html = txtContent;
+ }
+ me.execCommand('inserthtml', html, true);
+ me.__hasEnterExecCommand = false;
+ var rng = me.selection.getRange();
+ while (!domUtils.isBody(rng.startContainer) && !rng.startOffset &&
+ rng.startContainer[rng.startContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length
+ ) {
+ rng.setStartBefore(rng.startContainer);
+ }
+ var tmpAddress = rng.createAddress(true);
+ address.endAddress = tmpAddress.startAddress;
+ }
+ });
+
+ me.addListener('ready', function () {
+ domUtils.on(me.body, 'cut', function () {
+ var range = me.selection.getRange();
+ if (!range.collapsed && me.undoManger) {
+ me.undoManger.save();
+ }
+ });
+ //ie下beforepaste在点击右键时也会触发,所以用监控键盘才处理
+ domUtils.on(me.body, browser.ie || browser.opera ? 'keydown' : 'paste', function (e) {
+ if ((browser.ie || browser.opera) && ((!e.ctrlKey && !e.metaKey) || e.keyCode != '86')) {
+ return;
+ }
+ getClipboardData.call(me, function (div) {
+ filter(div);
+ });
});
+
+ });
+
+ me.commands['paste'] = {
+ execCommand: function (cmd) {
+ if (browser.ie) {
+ getClipboardData.call(me, function (div) {
+ filter(div);
+ });
+ me.document.execCommand('paste');
+ } else {
+ alert(me.getLang('pastemsg'));
+ }
+ }
}
-);
-
-// plugins/autoheight.js
-///import core
-///commands 当输入内容超过编辑器高度时,编辑器自动增高
-///commandsName AutoHeight,autoHeightEnabled
-///commandsTitle 自动增高
+};
+
+
+
+// plugins/puretxtpaste.js
/**
- * @description 自动伸展
- * @author zhanyi
+ * 纯文本粘贴插件
+ * @file
+ * @since 1.2.6.1
*/
-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(){
- try {
- 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';
+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);
}
- me.body.style.height = currentHeight + 'px';
- lastHeight = currentHeight;
}
- domUtils.removeStyle(node,'clear');
}
- } catch (e) {}
- },50)
- }
- }
- var isFullscreen;
- me.addListener('fullscreenchanged',function(cmd,f){
- isFullscreen = f
- });
- me.addListener('destroy', function () {
- me.removeListener('contentchange afterinserthtml keyup mouseup',adjustHeight)
- });
- me.enableAutoHeight = function () {
- var me = this;
- if (!me.autoHeightEnabled) {
- return;
- }
- var doc = me.document;
- me.autoHeightEnabled = true;
- bakOverflow = doc.body.style.overflowY;
- doc.body.style.overflowY = 'hidden';
- me.addListener('contentchange afterinserthtml keyup mouseup',adjustHeight);
- //ff不给事件算得不对
-
- setTimeout(function () {
- adjustHeight.call(me);
- }, browser.gecko ? 100 : 0);
- me.fireEvent('autoheightchanged', me.autoHeightEnabled);
- };
- me.disableAutoHeight = function () {
-
- me.body.style.overflowY = bakOverflow || '';
-
- me.removeListener('contentchange', adjustHeight);
- me.removeListener('keyup', adjustHeight);
- me.removeListener('mouseup', adjustHeight);
- me.autoHeightEnabled = false;
- me.fireEvent('autoheightchanged', me.autoHeightEnabled);
- };
-
- me.on('setHeight',function(){
- me.disableAutoHeight()
- });
- me.addListener('ready', function () {
- me.enableAutoHeight();
- //trace:1764
- var timer;
- domUtils.on(browser.ie ? me.body : me.document, browser.webkit ? 'dragover' : 'drop', function () {
- clearTimeout(timer);
- timer = setTimeout(function () {
- //trace:3681
- adjustHeight.call(me);
- }, 100);
-
- });
- //修复内容过多时,回到顶部,顶部内容被工具栏遮挡问题
- var lastScrollY;
- window.onscroll = function(){
- if(lastScrollY === null){
- lastScrollY = this.scrollY
- }else if(this.scrollY == 0 && lastScrollY != 0 && me.window){
- me.window.scrollTo(0,0);
- lastScrollY = null;
+ 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/autofloat.js
-///import core
-///commands 悬浮工具栏
-///commandsName AutoFloat,autoFloatEnabled
-///commandsTitle 悬浮工具栏
+// plugins/list.js
/**
- * modified by chengchao01
- * 注意: 引入此功能后,在IE6下会将body的背景图片覆盖掉!
+ * 有序列表,无序列表插件
+ * @file
+ * @since 1.2.6.1
*/
-UE.plugins['autofloat'] = function() {
- var me = this,
- lang = me.getLang();
- me.setOpt({
- topOffset:0
- });
- var optsAutoFloatEnabled = me.options.autoFloatEnabled !== false,
- topOffset = me.options.topOffset;
+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'
+ };
- //如果不固定toolbar的位置,则直接退出
- if(!optsAutoFloatEnabled){
- return;
+ 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 uiUtils = UE.ui.uiUtils,
- LteIE6 = browser.ie && browser.version <= 6,
- quirks = browser.quirks;
+ var listStyle = {
+ 'OL':listToArray(me.options.insertorderedlist),
+ 'UL':listToArray(me.options.insertunorderedlist)
+ };
+ var liiconpath = me.options.listiconpath;
- function checkHasUI(){
- if(!UE.ui){
- alert(lang.autofloatMsg);
- return 0;
+ //根据用户配置,调整customStyle
+ for(var s in customStyle){
+ if(!me.options.insertorderedlist.hasOwnProperty(s) && !me.options.insertunorderedlist.hasOwnProperty(s)){
+ delete customStyle[s];
}
- 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';
+
+ 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}');
}
- 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');
+ 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}');
}
}
- }
- 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);
+ 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{box-sizing:border-box;margin:0;pading:0;'+(browser.ie ? '' : 'width:95%')+'}li{clear:both;}'+customCss.join('\n'), me.document);
});
-
- me.addListener('ready', function(){
- if(checkHasUI(me)){
- //加载了ui组件,但在new时,没有加载ui,导致编辑器实例上没有ui类,所以这里做判断
- if(!me.ui){
- return;
- }
- getPosition = uiUtils.getClientRect;
- toolbarBox = me.ui.getDom('toolbarbox');
- orgTop = getPosition(toolbarBox).top;
- bakCssText = toolbarBox.style.cssText;
- placeHolder.style.height = toolbarBox.offsetHeight + 'px';
- if(LteIE6){
- fixIE6FixedPos();
- }
- domUtils.on(window, ['scroll','resize'], updateFloating);
- me.addListener('keydown', defer_updateFloating);
-
- me.addListener('beforefullscreenchange', function (t, enabled){
- if (enabled) {
- unsetFloating();
- }
- });
- me.addListener('fullscreenchanged', function (t, enabled){
- if (!enabled) {
- updateFloating();
+ //单独处理剪切的问题
+ me.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);
+ }
+ }
+ }
}
- });
- 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;
+ 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')
- /**
- * 创建插入视频字符窜
- * @param url 视频地址
- * @param width 视频宽度
- * @param height 视频高度
- * @param align 视频对齐
- * @param toEmbed 是否以flash代替显示
- * @param addParagraph 是否需要添加P 标签
- */
- function creatInsertStr(url,width,height,id,align,classname,type){
+ }
- url = utils.unhtmlForUrl(url);
- align = utils.unhtml(align);
- classname = utils.unhtml(classname);
+ 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)
- width = parseInt(width, 10) || 0;
- height = parseInt(height, 10) || 0;
+ }else{
+ n.setStyle('list-style-type',currentStyle)
+ }
+ })
- var str;
- switch (type){
- case 'image':
- str = ' '
- break;
- case 'embed':
- str = ' | |